diff --git a/src/components/Room/Room.test.tsx b/src/components/Room/Room.test.tsx index 69cb4adb6..7bee8dcb7 100644 --- a/src/components/Room/Room.test.tsx +++ b/src/components/Room/Room.test.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { renderHook } from '@testing-library/react-hooks'; -import Room from './Room'; +import Room, { useSetCollaborationViewOnScreenShare } from './Room'; import useChatContext from '../../hooks/useChatContext/useChatContext'; import useVideoContext from '../../hooks/useVideoContext/useVideoContext'; import { useAppState } from '../../state'; @@ -64,3 +65,46 @@ describe('the Room component', () => { expect(wrapper.find('GridView').exists()).toBe(true); }); }); + +describe('the useSetCollaborationViewOnScreenShare hook', () => { + const mockSetIsGridModeActive = jest.fn(); + beforeEach(jest.clearAllMocks); + + it('should not deactivate grid mode when there is no screen share participant', () => { + renderHook(() => + useSetCollaborationViewOnScreenShare(undefined, { localParticipant: {} } as any, mockSetIsGridModeActive) + ); + expect(mockSetIsGridModeActive).not.toBeCalled(); + }); + + it('should deactivate grid mode when a remote participant shares their screen', () => { + const { rerender } = renderHook( + ({ screenShareParticipant }) => + useSetCollaborationViewOnScreenShare( + screenShareParticipant, + { localParticipant: {} } as any, + mockSetIsGridModeActive + ), + { initialProps: { screenShareParticipant: undefined } } + ); + expect(mockSetIsGridModeActive).not.toBeCalled(); + rerender({ screenShareParticipant: {} } as any); + expect(mockSetIsGridModeActive).toBeCalledWith(false); + }); + + it('should not deactivate grid mode when the local participant shares their screen', () => { + const mockLocalParticipant = {}; + const { rerender } = renderHook( + ({ screenShareParticipant }) => + useSetCollaborationViewOnScreenShare( + screenShareParticipant, + { localParticipant: mockLocalParticipant } as any, + mockSetIsGridModeActive + ), + { initialProps: { screenShareParticipant: undefined } } + ); + expect(mockSetIsGridModeActive).not.toBeCalled(); + rerender({ screenShareParticipant: mockLocalParticipant } as any); + expect(mockSetIsGridModeActive).not.toBeCalled(); + }); +}); diff --git a/src/components/Room/Room.tsx b/src/components/Room/Room.tsx index 15d33c658..73186067a 100644 --- a/src/components/Room/Room.tsx +++ b/src/components/Room/Room.tsx @@ -1,16 +1,18 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import BackgroundSelectionDialog from '../BackgroundSelectionDialog/BackgroundSelectionDialog'; +import ChatWindow from '../ChatWindow/ChatWindow'; import clsx from 'clsx'; +import { GridView } from '../GridView/GridView'; +import { MobileGridView } from '../MobileGridView/MobileGridView'; +import MainParticipant from '../MainParticipant/MainParticipant'; import { makeStyles, Theme, useMediaQuery, useTheme } from '@material-ui/core'; -import ChatWindow from '../ChatWindow/ChatWindow'; +import { Participant, Room as IRoom } from 'twilio-video'; +import { ParticipantAudioTracks } from '../ParticipantAudioTracks/ParticipantAudioTracks'; import ParticipantList from '../ParticipantList/ParticipantList'; -import MainParticipant from '../MainParticipant/MainParticipant'; -import BackgroundSelectionDialog from '../BackgroundSelectionDialog/BackgroundSelectionDialog'; +import { useAppState } from '../../state'; import useChatContext from '../../hooks/useChatContext/useChatContext'; +import useScreenShareParticipant from '../../hooks/useScreenShareParticipant/useScreenShareParticipant'; import useVideoContext from '../../hooks/useVideoContext/useVideoContext'; -import { ParticipantAudioTracks } from '../ParticipantAudioTracks/ParticipantAudioTracks'; -import { GridView } from '../GridView/GridView'; -import { MobileGridView } from '../MobileGridView/MobileGridView'; -import { useAppState } from '../../state'; const useStyles = makeStyles((theme: Theme) => { const totalMobileSidebarHeight = `${theme.sidebarMobileHeight + @@ -32,13 +34,30 @@ const useStyles = makeStyles((theme: Theme) => { }; }); +export function useSetCollaborationViewOnScreenShare( + screenShareParticipant: Participant | undefined, + room: IRoom | null, + setIsGridModeActive: React.Dispatch> +) { + useEffect(() => { + if (screenShareParticipant && screenShareParticipant !== room!.localParticipant) { + setIsGridModeActive(false); + } + }, [screenShareParticipant, setIsGridModeActive, room]); +} + export default function Room() { const classes = useStyles(); const { isChatWindowOpen } = useChatContext(); - const { isBackgroundSelectionOpen } = useVideoContext(); - const { isGridModeActive } = useAppState(); + const { isBackgroundSelectionOpen, room } = useVideoContext(); + const { isGridModeActive, setIsGridModeActive } = useAppState(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const screenShareParticipant = useScreenShareParticipant(); + + // Here we switch to collaboration view when a participant starts sharing their screen, but + // the user is still free to switch back to grid mode. + useSetCollaborationViewOnScreenShare(screenShareParticipant, room, setIsGridModeActive); return (