import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import { useMeasure, useMedia } from 'react-use';
import {
HMSRoomState,
selectAppData,
selectIsLocalVideoEnabled,
selectIsVBEnabled,
selectLocalPeer,
selectRoomState,
selectVideoTrackByID,
useAVToggle,
useAwayNotifications,
useHMSStore,
useParticipants,
usePreviewJoin,
useRecordingStreaming,
} from '@100mslive/react-sdk';
import { MicOffIcon, SettingsIcon } from '@100mslive/react-icons';
import { Avatar, Box, config as cssConfig, Flex, flexCenter, styled, StyledVideoTile, Text, Video } from '../../..';
import { AudioLevel } from '../../../AudioLevel';
import { useHMSPrebuiltContext } from '../../AppContext';
import IconButton from '../../IconButton';
import SidePane from '../../layouts/SidePane';
import { AudioVideoToggle, NoiseCancellation } from '../AudioVideoToggle';
import Chip from '../Chip';
import TileConnection from '../Connection/TileConnection';
import FullPageProgress from '../FullPageProgress';
// @ts-ignore: No implicit Any
import { Logo } from '../Header/HeaderComponents';
// @ts-ignore: No implicit Any
import SettingsModal from '../Settings/SettingsModal';
import { VBToggle } from '../VirtualBackground/VBToggle';
import PreviewForm from './PreviewForm';
import { useRoomLayoutPreviewScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
import {
useAuthToken,
useUISettings,
// @ts-ignore: No implicit Any
} from '../AppData/useUISettings';
// @ts-ignore: No implicit Any
import { defaultPreviewPreference, UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences';
// @ts-ignore: No implicit Any
import { calculateAvatarAndAttribBoxSize, getFormattedCount } from '../../common/utils';
import { APP_DATA, UI_SETTINGS } from '../../common/constants';
const getParticipantChipContent = (peerCount = 0) => {
if (peerCount === 0) {
return 'You are the first to join';
}
const formattedNum = getFormattedCount(peerCount);
return `${formattedNum} other${parseInt(formattedNum) === 1 ? '' : 's'} in the session`;
};
const useLocalTileAspectRatio = () => {
const localPeer = useHMSStore(selectLocalPeer);
const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
const isMobile = useMedia(cssConfig.media.md);
let aspectRatio = 0;
if (videoTrack?.width && videoTrack?.height) {
aspectRatio = videoTrack.width / videoTrack.height;
} else {
aspectRatio = isMobile ? 9 / 16 : 16 / 9;
}
return aspectRatio.toString();
};
const PreviewJoin = ({
skipPreview,
initialName,
asRole,
}: {
skipPreview?: boolean;
initialName?: string;
asRole?: string;
}) => {
const [previewPreference, setPreviewPreference] = useUserPreferences(
UserPreferencesKeys.PREVIEW,
defaultPreviewPreference,
);
const { isStreamingOn } = useRecordingStreaming();
const authToken = useAuthToken();
const [name, setName] = useState(initialName || previewPreference.name);
const { toggleAudio, toggleVideo } = useAVToggle();
const [previewError, setPreviewError] = useState(false);
const { endpoints } = useHMSPrebuiltContext();
const { peerCount } = useParticipants();
const loadingEffects = useHMSStore(selectAppData(APP_DATA.loadingEffects));
const { enableJoin, preview, join } = usePreviewJoin({
name,
token: authToken,
initEndpoint: endpoints?.init,
initialSettings: {
isAudioMuted: skipPreview || previewPreference.isAudioMuted,
isVideoMuted: skipPreview || previewPreference.isVideoMuted,
speakerAutoSelectionBlacklist: ['Yeti Stereo Microphone'],
},
captureNetworkQualityInPreview: true,
handleError: (_, method) => {
if (method === 'preview') {
setPreviewError(true);
}
},
asRole,
});
const { requestPermission } = useAwayNotifications();
const roomState = useHMSStore(selectRoomState);
const savePreferenceAndJoin = useCallback(() => {
setPreviewPreference({
name,
});
join();
}, [join, name, setPreviewPreference]);
const { elements = {} } = useRoomLayoutPreviewScreen();
const { preview_header: previewHeader = {}, virtual_background } = elements || {};
const aspectRatio = useLocalTileAspectRatio();
useEffect(() => {
if (authToken) {
if (skipPreview) {
savePreferenceAndJoin();
} else {
preview().then(() => requestPermission());
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [authToken, skipPreview]);
useEffect(() => {
if (initialName) {
setName(initialName);
}
}, [initialName]);
return roomState === HMSRoomState.Preview ? (
{toggleVideo ? null : }
{previewHeader.title}
{previewHeader.sub_title}
{isStreamingOn ? (
}
/>
) : null}
{toggleVideo ? : null}
) : (
);
};
const Container = styled('div', {
width: '100%',
...flexCenter,
flexDirection: 'column',
px: '$10',
});
export const PreviewTile = ({ name, error }: { name: string; error?: boolean }) => {
const localPeer = useHMSStore(selectLocalPeer);
const { isLocalAudioEnabled, toggleAudio } = useAVToggle();
const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
const mirrorLocalVideo = useUISettings(UI_SETTINGS.mirrorLocalVideo);
const trackSelector = selectVideoTrackByID(localPeer?.videoTrack);
const track = useHMSStore(trackSelector);
const showMuteIcon = !isLocalAudioEnabled || !toggleAudio;
const aspectRatio = useLocalTileAspectRatio();
const [ref, { width: calculatedWidth, height: calculatedHeight }] = useMeasure();
const [avatarSize, attribBoxSize] = useMemo(
() => calculateAvatarAndAttribBoxSize(calculatedWidth, calculatedHeight),
[calculatedWidth, calculatedHeight],
);
return (
{localPeer ? (
<>
{!isVideoOn ? (
) : null}
>
) : null}
{!localPeer && !error ? : null}
{showMuteIcon ? (
) : (
)}
);
};
export const PreviewControls = ({ hideSettings, vbEnabled }: { hideSettings: boolean; vbEnabled: boolean }) => {
const isMobile = useMedia(cssConfig.media.md);
const isVBEnabledForUser = useHMSStore(selectIsVBEnabled);
return (
{vbEnabled && isVBEnabledForUser ? : null}
{isMobile && }
{!hideSettings ? : null}
);
};
export const PreviewSettings = React.memo(() => {
const [open, setOpen] = useState(false);
return (
setOpen(value => !value)}>
{open && }
);
});
export default PreviewJoin;