import React, { useCallback, useMemo } from "react"; import styles from "./InCallView.module.css"; import { HangupButton, MicButton, VideoButton, ScreenshareButton, } from "../button"; import { Header, LeftNav, RightNav, RoomHeaderInfo } from "../Header"; import { VideoGrid, useVideoGridLayout } from "../video-grid/VideoGrid"; import { VideoTileContainer } from "../video-grid/VideoTileContainer"; import { getAvatarUrl } from "../matrix-utils"; import { GroupCallInspector } from "./GroupCallInspector"; import { OverflowMenu } from "./OverflowMenu"; import { GridLayoutMenu } from "./GridLayoutMenu"; import { Avatar } from "../Avatar"; import { UserMenuContainer } from "../UserMenuContainer"; import { useRageshakeRequestModal } from "../settings/submit-rageshake"; import { RageshakeRequestModal } from "./RageshakeRequestModal"; import { usePreventScroll } from "@react-aria/overlays"; import { useMediaHandler } from "../settings/useMediaHandler"; const canScreenshare = "getDisplayMedia" in navigator.mediaDevices; // There is currently a bug in Safari our our code with cloning and sending MediaStreams // or with getUsermedia and getDisplaymedia being used within the same session. // For now we can disable screensharing in Safari. const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); export function InCallView({ client, groupCall, roomName, microphoneMuted, localVideoMuted, toggleLocalVideoMuted, toggleMicrophoneMuted, userMediaFeeds, activeSpeaker, onLeave, toggleScreensharing, isScreensharing, screenshareFeeds, setShowInspector, showInspector, roomId, }) { usePreventScroll(); const [layout, setLayout] = useVideoGridLayout(screenshareFeeds.length > 0); const { audioOutput } = useMediaHandler(); const items = useMemo(() => { const participants = []; for (const callFeed of userMediaFeeds) { participants.push({ id: callFeed.stream.id, callFeed, focused: screenshareFeeds.length === 0 && layout === "spotlight" ? callFeed.userId === activeSpeaker : false, isLocal: callFeed.isLocal(), }); } for (const callFeed of screenshareFeeds) { const userMediaItem = participants.find( (item) => item.callFeed.userId === callFeed.userId ); if (userMediaItem) { userMediaItem.presenter = true; } participants.push({ id: callFeed.stream.id, callFeed, focused: true, isLocal: callFeed.isLocal(), }); } return participants; }, [userMediaFeeds, activeSpeaker, screenshareFeeds, layout]); const onFocusTile = useCallback( (tiles, focusedTile) => { if (layout === "freedom") { return tiles.map((tile) => { if (tile === focusedTile) { return { ...tile, focused: !tile.focused }; } return tile; }); } else { return tiles; } }, [layout, setLayout] ); const renderAvatar = useCallback( (roomMember, width, height) => { const avatarUrl = roomMember.user?.avatarUrl; const size = Math.round(Math.min(width, height) / 2); return ( ); }, [client] ); const { modalState: rageshakeRequestModalState, modalProps: rageshakeRequestModalProps, } = useRageshakeRequestModal(groupCall.room.roomId); return (
{items.length === 0 ? (

Waiting for other participants...

) : ( {({ item, ...rest }) => ( 2 || item.focused} audioOutputDevice={audioOutput} disableSpeakingIndicator={items.length < 3} {...rest} /> )} )}
{canScreenshare && !isSafari && ( )}
{rageshakeRequestModalState.isOpen && ( )}
); }