import React, { useCallback, useEffect, useState } from 'react'; import { Box, Button, Icon, Icons, Spinner, Text } from 'folds'; import { SequenceCard } from '../../components/sequence-card'; import * as css from './styles.css'; import { ChatButton, ControlDivider, MicrophoneButton, SoundButton, VideoButton } from './Controls'; import { useIsDirectRoom, useRoom } from '../../hooks/useRoom'; import { useCallEmbed, useCallJoined, useCallStart } from '../../hooks/useCallEmbed'; import { useCallPreferences } from '../../state/hooks/callPreferences'; import { useSetting } from '../../state/hooks/settings'; import { settingsAtom } from '../../state/settings'; type MediaPermState = 'granted' | 'denied' | 'prompt' | 'unknown'; function useMediaPermissions(): MediaPermState { const [state, setState] = useState('unknown'); useEffect(() => { if (!navigator.permissions) { setState('unknown'); return; } navigator.permissions .query({ name: 'microphone' as unknown as PermissionDescriptor['name'] }) .then((result) => { setState(result.state as MediaPermState); result.onchange = () => setState(result.state as MediaPermState); }) .catch(() => setState('unknown')); }, []); return state; } type PrescreenControlsProps = { canJoin?: boolean; }; export function PrescreenControls({ canJoin }: PrescreenControlsProps) { const room = useRoom(); const callEmbed = useCallEmbed(); const callJoined = useCallJoined(callEmbed); const direct = useIsDirectRoom(); const inOtherCall = callEmbed && callEmbed.roomId !== room.roomId; const startCall = useCallStart(direct); const joining = callEmbed?.roomId === room.roomId && !callJoined; const micPermission = useMediaPermissions(); const micDenied = micPermission === 'denied'; const disabled = inOtherCall || !canJoin || micDenied; const { microphone, video, sound, toggleMicrophone, toggleVideo, toggleSound } = useCallPreferences(); const [cameraOnJoin] = useSetting(settingsAtom, 'cameraOnJoin'); const handleMicrophoneToggle = useCallback(async () => toggleMicrophone(), [toggleMicrophone]); const handleVideoToggle = useCallback(async () => toggleVideo(), [toggleVideo]); return ( {micDenied && ( Microphone access is blocked. Enable it in your browser settings to join. )} ); }