Add remote video overlay

Fix remote audio not working when viewing another conversation.
Add a remote video overlay when in a call, but viewing a different page.

New components:
- VideoOverlay
- RemoteVideoOverlay: Video overlay for the remote stream when in a
  different page. Clicking it will redirect to the current call page.
- VideoStream: renders a video from a MediaStream and can
  output audio to the device with id `audioOutDeviceId`

Misc changes:
- Can click local video to make bigger

Change-Id: If1bb0b10c137944c405d540f041ebfe8005f9251
diff --git a/client/src/components/VideoOverlay.tsx b/client/src/components/VideoOverlay.tsx
new file mode 100644
index 0000000..93106ab
--- /dev/null
+++ b/client/src/components/VideoOverlay.tsx
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { Box } from '@mui/material';
+import { useContext, useRef, useState } from 'react';
+import Draggable, { DraggableEventHandler } from 'react-draggable';
+import { useNavigate } from 'react-router-dom';
+
+import { CallContext } from '../contexts/CallProvider';
+import { WebRtcContext } from '../contexts/WebRtcProvider';
+import { VideoElementWithSinkId } from '../utils/utils';
+import VideoStream, { VideoStreamProps } from './VideoStream';
+
+type Size = 'small' | 'medium' | 'large';
+export type VideoOverlayProps = VideoStreamProps & {
+  onClick?: DraggableEventHandler;
+  size?: Size;
+};
+
+const sizeToDimentions: Record<Size, string> = {
+  small: '25%',
+  medium: '50%',
+  large: '75%',
+};
+
+const VideoOverlay = ({ onClick, size = 'medium', ...props }: VideoOverlayProps) => {
+  const videoRef = useRef<VideoElementWithSinkId | null>(null);
+  const [dragging, setDragging] = useState(false);
+
+  return (
+    <Box position="relative" width="100%" height="100%">
+      <Draggable
+        onDrag={() => setDragging(true)}
+        onStop={(...args) => {
+          if (!dragging && onClick) {
+            onClick(...args);
+          }
+
+          setDragging(false);
+        }}
+        bounds="parent"
+        nodeRef={videoRef}
+      >
+        <VideoStream
+          ref={videoRef}
+          {...props}
+          style={{
+            position: 'absolute',
+            right: 0,
+            borderRadius: '12px',
+            maxHeight: sizeToDimentions[size],
+            maxWidth: sizeToDimentions[size],
+            zIndex: 2,
+            transition: 'max-width, max-height .2s ease-in-out',
+            ...props.style,
+          }}
+        />
+      </Draggable>
+    </Box>
+  );
+};
+
+export const RemoteVideoOverlay = ({ callConversationId }: { callConversationId: string }) => {
+  const { remoteStreams } = useContext(WebRtcContext);
+  const {
+    currentMediaDeviceIds: {
+      audiooutput: { id: audioOutDeviceId },
+    },
+  } = useContext(CallContext);
+  const navigate = useNavigate();
+
+  // 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 stream = remoteStreams?.at(0);
+
+  return (
+    <Box position="absolute" width="100%" height="100%" display="flex">
+      <Box margin={2} flexGrow={1}>
+        <VideoOverlay
+          stream={stream}
+          audioOutDeviceId={audioOutDeviceId}
+          onClick={() => {
+            navigate(`/conversation/${callConversationId}`);
+          }}
+          size={'small'}
+        />
+      </Box>
+    </Box>
+  );
+};
+
+export default VideoOverlay;