diff --git a/ts/components/session/calling/CallContainer.tsx b/ts/components/session/calling/CallContainer.tsx index cf4bd433e..ef1a51781 100644 --- a/ts/components/session/calling/CallContainer.tsx +++ b/ts/components/session/calling/CallContainer.tsx @@ -110,7 +110,8 @@ export const CallContainer = () => { {ongoingCallProps.name} - + + diff --git a/ts/session/utils/CallManager.ts b/ts/session/utils/CallManager.ts index 25e8e4f19..28b737947 100644 --- a/ts/session/utils/CallManager.ts +++ b/ts/session/utils/CallManager.ts @@ -1,6 +1,12 @@ import _ from 'lodash'; import { SignalService } from '../../protobuf'; -import { answerCall, callConnected, endCall, incomingCall } from '../../state/ducks/conversations'; +import { + answerCall, + callConnected, + endCall, + incomingCall, + startingCallWith, +} from '../../state/ducks/conversations'; import { CallMessage } from '../messages/outgoing/controlMessage/CallMessage'; import { ed25519Str } from '../onions/onionPath'; import { getMessageQueue } from '../sending'; @@ -13,7 +19,7 @@ const callCache = new Map>(); let peerConnection: RTCPeerConnection | null; -const ENABLE_VIDEO = false; +const ENABLE_VIDEO = true; const configuration = { configuration: { @@ -32,7 +38,7 @@ const configuration = { // tslint:disable-next-line: function-name export async function USER_callRecipient(recipient: string) { window?.log?.info(`starting call with ${ed25519Str(recipient)}..`); - + window.inboxStore?.dispatch(startingCallWith({ pubkey: recipient })); if (peerConnection) { window.log.info('closing existing peerconnection'); peerConnection.close(); @@ -50,7 +56,9 @@ export async function USER_callRecipient(recipient: string) { window.inboxStore?.dispatch(callConnected({ pubkey: recipient })); } }); - + peerConnection.addEventListener('ontrack', event => { + console.warn('ontrack:', event); + }); peerConnection.addEventListener('icecandidate', event => { // window.log.warn('event.candidate', event.candidate); @@ -60,6 +68,20 @@ export async function USER_callRecipient(recipient: string) { } }); + const localVideo = document.querySelector('#video-local') as any; + if (localVideo) { + localVideo.srcObject = mediaDevices; + } + const remoteStream = new MediaStream(); + + peerConnection.addEventListener('track', event => { + const remoteVideo = document.querySelector('#video-remote') as any; + if (remoteVideo) { + remoteVideo.srcObject = remoteStream; + } + remoteStream.addTrack(event.track); + }); + const offerDescription = await peerConnection.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: ENABLE_VIDEO, @@ -155,6 +177,7 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) { ); return; } + window.inboxStore?.dispatch(answerCall({ pubkey: fromSender })); if (peerConnection) { window.log.info('closing existing peerconnection'); @@ -167,19 +190,20 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) { // window.log.info('USER_acceptIncomingCallRequest adding track ', track); peerConnection?.addTrack(track, mediaDevices); }); - peerConnection.addEventListener('icecandidateerror', event => { - console.warn('icecandidateerror:', event); - }); - peerConnection.addEventListener('negotiationneeded', event => { - console.warn('negotiationneeded:', event); - }); - peerConnection.addEventListener('signalingstatechange', _event => { - // console.warn('signalingstatechange:', event); - }); + const localVideo = document.querySelector('#video-local') as any; + if (localVideo) { + localVideo.srcObject = mediaDevices; + } - peerConnection.addEventListener('ontrack', event => { - console.warn('ontrack:', event); + const remoteStream = new MediaStream(); + + peerConnection.addEventListener('track', event => { + const remoteVideo = document.querySelector('#video-remote') as any; + if (remoteVideo) { + remoteVideo.srcObject = remoteStream; + } + remoteStream.addTrack(event.track); }); peerConnection.addEventListener('connectionstatechange', _event => { window.log.info( @@ -238,8 +262,6 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) { window.log.info('sending ANSWER MESSAGE'); await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(fromSender), callAnswerMessage); - - window.inboxStore?.dispatch(answerCall({ pubkey: fromSender })); } // tslint:disable-next-line: function-name @@ -258,6 +280,14 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) { export function handleEndCallMessage(sender: string) { callCache.delete(sender); + const remoteVideo = document.querySelector('#video-remote') as any; + if (remoteVideo) { + remoteVideo.srcObject = null; + } + const localVideo = document.querySelector('#video-local') as any; + if (localVideo) { + localVideo.srcObject = null; + } // // FIXME audric trigger UI cleanup window.inboxStore?.dispatch(endCall({ pubkey: sender })); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 1319c044a..f31be1a8a 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -824,6 +824,23 @@ const conversationsSlice = createSlice({ void foundConvo.commit(); return state; }, + startingCallWith(state: ConversationsStateType, action: PayloadAction<{ pubkey: string }>) { + const callerPubkey = action.payload.pubkey; + const existingCallState = state.conversationLookup[callerPubkey].callState; + if (existingCallState && existingCallState !== 'none') { + return state; + } + const foundConvo = getConversationController().get(callerPubkey); + if (!foundConvo) { + return state; + } + // we have to update the model itself. + // not the db (as we dont want to store that field in it) + // and not the redux store directly as it gets overriden by the commit() of the conversationModel + foundConvo.callState = 'offering'; + void foundConvo.commit(); + return state; + }, }, extraReducers: (builder: any) => { // Add reducers for additional action types here, and handle loading state as needed @@ -888,6 +905,7 @@ export const { endCall, answerCall, callConnected, + startingCallWith, } = actions; export async function openConversationWithMessages(args: {