| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -49,6 +49,7 @@ export function setVideoEventsListener(listener: CallManagerListener) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				const callCache = new Map<string, Array<SignalService.CallMessage>>();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				let peerConnection: RTCPeerConnection | null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				let dataChannel: RTCDataChannel | null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				let remoteStream: MediaStream | null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				let mediaDevices: MediaStream | null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				export const INPUT_DISABLED_DEVICE_ID = 'off';
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -196,14 +197,14 @@ export async function selectAudioInputByDeviceId(audioInputDeviceId: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				async function handleNegotiationNeededEvent(event: Event, recipient: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  window.log?.warn('negotiationneeded:', event);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				async function handleNegotiationNeededEvent(_event: Event, recipient: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  try {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    makingOffer = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const offer = await peerConnection?.createOffer();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!offer) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      throw new Error('Could not create offer in handleNegotiationNeededEvent');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.info('got handleNegotiationNeeded event. creating offer');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const offer = await peerConnection?.createOffer({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      offerToReceiveAudio: true,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      offerToReceiveVideo: true,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    await peerConnection?.setLocalDescription(offer);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (offer && offer.sdp) {
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -292,7 +293,7 @@ export async function USER_callRecipient(recipient: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    throw new Error('USER_callRecipient peerConnection is already initialized ');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection = createOrGetPeerConnection(recipient);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection = createOrGetPeerConnection(recipient, true);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  await openMediaDevicesAndAddTracks();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -370,6 +371,10 @@ function closeVideoCall() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    peerConnection.onicegatheringstatechange = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    peerConnection.onnegotiationneeded = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (dataChannel) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      dataChannel.close();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      dataChannel = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (mediaDevices) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      mediaDevices.getTracks().forEach(track => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        track.stop();
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -393,7 +398,7 @@ function closeVideoCall() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				function createOrGetPeerConnection(withPubkey: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				function createOrGetPeerConnection(withPubkey: string, createDataChannel: boolean) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return peerConnection;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -403,6 +408,46 @@ function createOrGetPeerConnection(withPubkey: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection.onnegotiationneeded = async (event: Event) => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    await handleNegotiationNeededEvent(event, withPubkey);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection.ondatachannel = e => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (!createDataChannel) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      dataChannel = e.channel;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      console.warn('ondatachannel');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setInterval(() => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        console.warn('ondatachannel: sending yoooooo');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        dataChannel?.send('yooooooooooooooo: ' + Date.now());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }, 1000);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      dataChannel.onmessage = e => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        console.warn('ondatachannel: datachannel on message', e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (createDataChannel) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    console.warn('createOrGetPeerConnection: createDataChannel');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dataChannel = peerConnection.createDataChannel('session-datachannel');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dataChannel.onmessage = e => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      console.warn('createDataChannel: datachannel on message', e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dataChannel.onopen = () => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.log.info('onopen of datachannel');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const videoEnabledLocally =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        selectedCameraId !== undefined && selectedCameraId !== INPUT_DISABLED_DEVICE_ID;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      dataChannel?.send(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        JSON.stringify({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          video: videoEnabledLocally,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dataChannel.onclose = () => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.log.info('onclose of datachannel');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection.onsignalingstatechange = handleSignalingStateChangeEvent;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection.ontrack = event => {
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -453,7 +498,7 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    throw new Error('USER_acceptIncomingCallRequest: peerConnection is already set.');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection = createOrGetPeerConnection(fromSender);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  peerConnection = createOrGetPeerConnection(fromSender, false);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  await openMediaDevicesAndAddTracks();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -561,22 +606,8 @@ export async function handleCallTypeOffer(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const convos = getConversationController().getConversations();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const callingConvos = convos.filter(convo => convo.callState !== undefined);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (callingConvos.length > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // we just got a new offer from someone we are already in a call with
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (callingConvos.length === 1 && callingConvos[0].id === sender) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        window.log.info('Got a new offer message from our ongoing call');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const remoteDesc = new RTCSessionDescription({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          type: 'offer',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          sdp: callMessage.sdps[0],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          await peerConnection.setRemoteDescription(remoteDesc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          remoteStream?.getTracks().forEach(t => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            remoteStream?.removeTrack(t);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          await buildAnswerAndSendIt(sender);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // we just got a new offer from someone we are NOT already in a call with
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (callingConvos.length !== 1 || callingConvos[0].id !== sender) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        await handleMissedCall(sender, incomingOfferTimestamp);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -585,12 +616,28 @@ export async function handleCallTypeOffer(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const readyForOffer =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      !makingOffer && (peerConnection?.signalingState === 'stable' || isSettingRemoteAnswerPending);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const polite = lastOutgoingOfferTimestamp < incomingOfferTimestamp;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ignoreOffer = !polite && !readyForOffer;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const offerCollision = !readyForOffer;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ignoreOffer = !polite && offerCollision;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (ignoreOffer) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // window.log?.warn('Received offer when unready for offer; Ignoring offer.');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.log?.warn('Received offer when unready for offer; Ignoring offer.');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if (callingConvos.length === 1 && callingConvos[0].id === sender) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      window.log.info('Got a new offer message from our ongoing call');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      isSettingRemoteAnswerPending = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const remoteDesc = new RTCSessionDescription({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        type: 'offer',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        sdp: callMessage.sdps[0],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      isSettingRemoteAnswerPending = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        await peerConnection.setRemoteDescription(remoteDesc); // SRD rolls back as needed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        await buildAnswerAndSendIt(sender);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // don't need to do the sending here as we dispatch an answer in a
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } catch (err) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log?.error(`Error handling offer message ${err}`);
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -626,6 +673,7 @@ export async function handleCallTypeAnswer(sender: string, callMessage: SignalSe
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.warn('cannot handle answered message without signal description protols');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  window.log.info('handling callMessage ANSWER');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!callCache.has(sender)) {
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -633,16 +681,18 @@ export async function handleCallTypeAnswer(sender: string, callMessage: SignalSe
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  callCache.get(sender)?.push(callMessage);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.info('handleCallTypeAnswer without peer connection. Dropping');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  window.inboxStore?.dispatch(answerCall({ pubkey: sender }));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const remoteDesc = new RTCSessionDescription({ type: 'answer', sdp: callMessage.sdps[0] });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (peerConnection) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // window.log?.info('Setting remote answer pending');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    isSettingRemoteAnswerPending = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    await peerConnection.setRemoteDescription(remoteDesc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    isSettingRemoteAnswerPending = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.log.info('call answered by recipient but we do not have a peerconnection set');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // window.log?.info('Setting remote answer pending');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  isSettingRemoteAnswerPending = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  await peerConnection?.setRemoteDescription(remoteDesc); // SRD rolls back as needed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  isSettingRemoteAnswerPending = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				export async function handleCallTypeIceCandidates(
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |