diff --git a/custom/fitness-demo/components/Call/Container.js b/custom/fitness-demo/components/Call/Container.js index 22e0d08..5e9cb68 100644 --- a/custom/fitness-demo/components/Call/Container.js +++ b/custom/fitness-demo/components/Call/Container.js @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import { Audio } from '@custom/shared/components/Audio'; import { BasicTray } from '@custom/shared/components/Tray'; import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; -import useJoinSound from '@custom/shared/hooks/useJoinSound'; +import { useJoinSound } from '@custom/shared/hooks/useJoinSound'; import PropTypes from 'prop-types'; import { WaitingRoom } from './WaitingRoom'; diff --git a/custom/shared/components/DeviceSelect/DeviceSelect.js b/custom/shared/components/DeviceSelect/DeviceSelect.js index f0b0153..b47c63e 100644 --- a/custom/shared/components/DeviceSelect/DeviceSelect.js +++ b/custom/shared/components/DeviceSelect/DeviceSelect.js @@ -8,13 +8,15 @@ export const DeviceSelect = () => { cams, mics, speakers, - currentDevices, - setCamDevice, - setMicDevice, - setSpeakersDevice, + currentCam, + setCurrentCam, + currentMic, + setCurrentMic, + currentSpeaker, + setCurrentSpeaker, } = useMediaDevices(); - if (!currentDevices) { + if (!currentCam && !currentMic && !currentSpeaker) { return
Loading devices...
; } @@ -22,9 +24,9 @@ export const DeviceSelect = () => { <> setCamDevice(cams[e.target.value])} + onChange={(e) => setCurrentCam(cams[e.target.value])} value={cams.findIndex( - (i) => i.deviceId === currentDevices.camera.deviceId + (i) => i.deviceId === currentCam.deviceId )} > {cams.map(({ deviceId, label }, i) => ( @@ -37,9 +39,9 @@ export const DeviceSelect = () => { setMicDevice(mics[e.target.value])} + onChange={(e) => setCurrentMic(mics[e.target.value])} value={mics.findIndex( - (i) => i.deviceId === currentDevices.mic.deviceId + (i) => i.deviceId === currentMic.deviceId )} > {mics.map(({ deviceId, label }, i) => ( @@ -56,9 +58,9 @@ export const DeviceSelect = () => { {speakers.length > 0 && ( setSpeakersDevice(speakers[e.target.value])} + onChange={(e) => setCurrentSpeaker(speakers[e.target.value])} value={speakers.findIndex( - (i) => i.deviceId === currentDevices.speaker.deviceId + (i) => i.deviceId === currentSpeaker.deviceId )} > {speakers.map(({ deviceId, label }, i) => ( diff --git a/custom/shared/components/Tile/Video.js b/custom/shared/components/Tile/Video.js index 5e975be..c9541cc 100644 --- a/custom/shared/components/Tile/Video.js +++ b/custom/shared/components/Tile/Video.js @@ -1,36 +1,10 @@ -import React, { useMemo, forwardRef, memo, useEffect, useState } from 'react'; -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { isScreenId } from '@custom/shared/contexts/participantsState'; +import React, { useMemo, forwardRef, memo, useEffect } from 'react'; import Bowser from 'bowser'; -import classNames from 'classnames'; import PropTypes from 'prop-types'; import { shallowEqualObjects } from 'shallow-equal'; -import { useDeepCompareMemo } from 'use-deep-compare'; export const Video = memo( - forwardRef(({ fit = 'contain', participantId, videoTrack, ...rest }, videoEl) => { - const { callObject } = useCallState(); - const { isMobile } = useUIState(); - - const isLocalCam = useMemo(() => { - const localParticipant = callObject.participants()?.local; - return participantId === localParticipant.session_id && !isScreenId(participantId); - }, [callObject, participantId]); - - const [isMirrored, setIsMirrored] = useState(isLocalCam); - - /** - * Considered as playable video: - * - local cam feed - * - any screen share - * - remote cam feed that is subscribed and reported as playable - */ - const isPlayable = useDeepCompareMemo( - () => isLocalCam || isScreenId(participantId), - [isLocalCam, isScreenId(participantId)] - ); - + forwardRef(({ participantId, videoTrack, ...rest }, videoEl) => { /** * Memo: Chrome >= 92? * See: https://bugs.chromium.org/p/chromium/issues/detail?id=1232649 @@ -45,114 +19,33 @@ export const Video = memo( }, []); /** - * Determine if video needs to be mirrored. - */ - useEffect(() => { - if (!videoTrack) return; - - const videoTrackSettings = videoTrack.getSettings(); - const isUsersFrontCamera = - 'facingMode' in videoTrackSettings - ? isLocalCam && videoTrackSettings.facingMode === 'user' - : isLocalCam; - // only apply mirror effect to user facing camera - if (isMirrored !== isUsersFrontCamera) { - setIsMirrored(isUsersFrontCamera); - } - }, [isMirrored, isLocalCam, videoTrack]); - - /** - * Handle canplay & picture-in-picture events. + * Effect: Umount + * Note: nullify src to ensure media object is not counted */ useEffect(() => { const video = videoEl.current; - if (!video) return; - const handleCanPlay = () => { - if (!video.paused) return; - video.play(); - }; - const handleEnterPIP = () => { - video.style.transform = 'scale(1)'; - }; - const handleLeavePIP = () => { - video.style.transform = ''; - setTimeout(() => { - if (video.paused) video.play(); - }, 100); - }; - video.addEventListener('canplay', handleCanPlay); - video.addEventListener('enterpictureinpicture', handleEnterPIP); - video.addEventListener('leavepictureinpicture', handleLeavePIP); - return () => { - video.removeEventListener('canplay', handleCanPlay); - video.removeEventListener('enterpictureinpicture', handleEnterPIP); - video.removeEventListener('leavepictureinpicture', handleLeavePIP); - }; - }, [isChrome92, videoEl]); - - /** - * Update srcObject. - */ - useEffect(() => { - const video = videoEl.current; - if (!video || !videoTrack) return; - video.srcObject = new MediaStream([videoTrack]); + if (!video) return false; + // clean up when video renders for different participant + video.srcObject = null; if (isChrome92) video.load(); return () => { // clean up when unmounted video.srcObject = null; if (isChrome92) video.load(); }; - }, [isChrome92, participantId, videoEl, videoTrack, videoTrack?.id]); + }, [videoEl, isChrome92, participantId]); - return ( - <> -