import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { useHMSTheme } from '../../hooks/HMSThemeProvider'; import startCase from 'lodash/startCase'; import { closeMediaStream } from '../../utils'; import { getLocalStream } from '@100mslive/100ms-web-sdk'; import { hmsUiClassParserGenerator } from '../../utils/classes'; import { BrowserOSError, getLocalStreamException, isBrowserOSValid, } from '../../utils/preview'; import { MessageModal } from '../MessageModal'; import { SettingsFormProps } from '../Settings/Settings'; import { Button } from '../TwButton'; import { VideoTile, VideoTileProps } from '../VideoTile'; import { VideoTileClasses } from '../VideoTile/VideoTile'; import { VideoTileControls } from './Controls'; import HMSLogger from '../../utils/ui-logger'; import { Text } from '../Text'; import { HMSPeer } from '../../store/schema'; interface MuteStatus { audioMuted?: boolean; videoMuted?: boolean; } export interface PreviewClasses { root?: string; containerRoot?: string; header?: string; messageModal?: string; helloDiv?: string; joinButton?: string; goBackButton?: string; } const defaultClasses: PreviewClasses = { root: 'flex h-screen w-screen bg-white dark:bg-black justify-center items-center', containerRoot: 'flex flex-col items-center w-37.5 h-400 box-border bg-gray-600 dark:bg-gray-100 text-gray-100 dark:text-white overflow-hidden rounded-2xl', header: 'w-22.5 h-22.5 mt-1.875 mb-7', helloDiv: 'text-2xl font-medium mb-12', }; export interface PreviewProps { name: string; joinOnClick: ({ audioMuted, videoMuted }: MuteStatus) => void; onChange: (values: SettingsFormProps) => void; goBackOnClick: () => void; videoTileProps?: Partial; videoTileClasses?: VideoTileClasses; /** * extra classes added by user */ classes?: PreviewClasses; } export const Preview = ({ name, joinOnClick, goBackOnClick, onChange, videoTileProps, classes, videoTileClasses, }: PreviewProps) => { const { tw } = useHMSTheme(); const styler = useMemo( () => hmsUiClassParserGenerator({ tw, classes, defaultClasses, tag: 'hmsui-preview', }), [], ); const [mediaStream, setMediaStream] = useState(new MediaStream()); const [error, setError] = useState({ title: '', message: '', }); const [audioMuted, setAudioMuted] = useState(false); const [videoMuted, setVideoMuted] = useState(false); const [selectedAudioInput, setSelectedAudioInput] = useState('default'); const [selectedVideoInput, setSelectedVideoInput] = useState('default'); const toggleMediaState = (type: string) => { if (type === 'audio') { mediaStream.getAudioTracks()[0].enabled = audioMuted; setAudioMuted(prevMuted => !prevMuted); } else if (type === 'video') { mediaStream.getVideoTracks()[0].enabled = videoMuted; setVideoMuted(prevMuted => !prevMuted); } }; const [showModal, setShowModal] = useState(false); useEffect(() => { setShowModal(Boolean(error.title)); }, [error.title]); const startMediaStream = async () => { closeMediaStream(mediaStream); try { if (isBrowserOSValid()) { const stream = await getLocalStream({ audio: { deviceId: selectedAudioInput }, video: { deviceId: selectedVideoInput }, }); setMediaStream(stream); } } catch (err) { HMSLogger.e('[Preview]', err.name, err.message); if (err instanceof BrowserOSError) { const localStreamError = getLocalStreamException(err.name); setError(localStreamError); } else { setError({ title: startCase(err.title), message: err.message, }); } } }; window.onunload = () => closeMediaStream(mediaStream); useEffect(() => { startMediaStream(); return () => { closeMediaStream(mediaStream); }; }, [selectedAudioInput, selectedVideoInput]); const handleDeviceChange = useCallback((values: SettingsFormProps) => { values?.selectedAudioInput && setSelectedAudioInput(values.selectedAudioInput); values?.selectedVideoInput && setSelectedVideoInput(values.selectedVideoInput); onChange(values); }, []); return ( // root
{/* header */}
{/* messageModal */} {/* videoTile */} toggleMediaState('audio')} videoButtonOnClick={() => toggleMediaState('video')} isAudioMuted={audioMuted} isVideoMuted={videoMuted} onChange={handleDeviceChange} /> } />
{/* helloDiv */}
Hello, {name}
{/* joinButton */}
); };