Improve permission handling in call flow
Improve permission handling by asking the user to give mic and camera permissions before sending `CallBegin` or `CallAccept` for the caller and receiver respectively.
Followed the flow described here: https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Connectivity#session_descriptions
CallProvider:
- Change functions order to place listeners under the function that sends the corresponding WebSocket message.
- Replace `Default` CallStatus with `Loading` for when asking user permissions before sending the `CallBegin`/`CallAccept` message.
- Remove `localStream` and `remoteStream` from `CallContext`. They are now available only in `WebRtcContext`.
- Replace `setAudioStatus` and `setVideoStatus` with `setIsAudioOn` and `setIsVideoOn`. A `useEffect` is now used to disable the tracks when the audio/video status changes.
WebRtcProvider:
- Move WebRTC connection close logic to WebRtcProvider
- Remove `webRtcConnection` from `WebRtcContext`. `WebRtcProvider` is now in charge of setting everything related to the WebRTC Connection.
UI:
- Add `CallPermissionDenied` page for when permissions are denied.
- Rework `CallPending` to display `Loading...` when waiting for user permissions
Change-Id: I48153577cca4c73cdb9b81d2fa78cfdfe2e06d69
diff --git a/client/src/pages/CallInterface.tsx b/client/src/pages/CallInterface.tsx
index 4daa1cd..beef803 100644
--- a/client/src/pages/CallInterface.tsx
+++ b/client/src/pages/CallInterface.tsx
@@ -29,7 +29,6 @@
useState,
} from 'react';
import Draggable from 'react-draggable';
-import { useLocation } from 'react-router-dom';
import { ExpandableButtonProps } from '../components/Button';
import {
@@ -48,12 +47,12 @@
import CallChatDrawer from '../components/CallChatDrawer';
import { CallContext, CallStatus } from '../contexts/CallProvider';
import { ConversationContext } from '../contexts/ConversationProvider';
+import { WebRtcContext } from '../contexts/WebRtcProvider';
import { CallPending } from './CallPending';
export default () => {
- const { callRole, callStatus, isChatShown, isFullscreen } = useContext(CallContext);
+ const { callStatus, isChatShown, isFullscreen } = useContext(CallContext);
const callInterfaceRef = useRef<HTMLDivElement>();
- const { state } = useLocation();
useEffect(() => {
if (!callInterfaceRef.current) {
@@ -68,13 +67,7 @@
}, [isFullscreen]);
if (callStatus !== CallStatus.InCall) {
- return (
- <CallPending
- pending={callRole}
- caller={callStatus === CallStatus.Connecting ? 'connecting' : 'calling'}
- medium={state?.isVideoOn ? 'video' : 'audio'}
- />
- );
+ return <CallPending />;
}
return (
@@ -90,7 +83,8 @@
}
const CallInterface = () => {
- const { isVideoOn, localStream, remoteStream } = useContext(CallContext);
+ const { localStream, remoteStreams } = useContext(WebRtcContext);
+ const { isVideoOn } = useContext(CallContext);
const gridItemRef = useRef(null);
const remoteVideoRef = useRef<HTMLVideoElement | null>(null);
const localVideoRef = useRef<HTMLVideoElement | null>(null);
@@ -102,10 +96,13 @@
}, [localStream]);
useEffect(() => {
+ // TODO: For now, `remoteStream` is the first remote stream in the array.
+ // There should only be one in the array, but we should make sure this is right.
+ const remoteStream = remoteStreams?.at(0);
if (remoteStream && remoteVideoRef.current) {
remoteVideoRef.current.srcObject = remoteStream;
}
- }, [remoteStream]);
+ }, [remoteStreams]);
return (
<Box display="flex" flexGrow={1}>