import React, { Fragment } from 'react';
import { useMedia } from 'react-use';
import {
HMSException,
HMSSimulcastLayerDefinition,
HMSTrackID,
HMSVideoTrack,
selectAvailableRoleNames,
selectPermissions,
selectSessionStore,
selectTrackByID,
useCustomEvent,
useHMSActions,
useHMSStore,
useRemoteAVToggle,
} from '@100mslive/react-sdk';
import {
MicOffIcon,
MicOnIcon,
PencilIcon,
PersonSettingsIcon,
PinIcon,
RemoveUserIcon,
ShareScreenIcon,
ShrinkIcon,
SpeakerIcon,
StarIcon,
VideoOffIcon,
VideoOnIcon,
} from '@100mslive/react-icons';
import { Box, Flex } from '../../../Layout';
import { Slider } from '../../../Slider';
import { Text } from '../../../Text';
import { config as cssConfig } from '../../../Theme';
import { StyledMenuTile } from '../../../TileMenu';
import { useHMSPrebuiltContext } from '../../AppContext';
// @ts-ignore
import { ToastManager } from '../Toast/ToastManager';
// @ts-ignore
import { useSetAppDataByKey } from '../AppData/useUISettings';
// @ts-ignore
import { useDropdownSelection } from '../hooks/useDropdownSelection';
import { getDragClassName } from './utils';
import { APP_DATA, isIOS, REMOTE_STOP_SCREENSHARE_TYPE, SESSION_STORE_KEY } from '../../common/constants';
export const isSameTile = ({
trackId,
videoTrackID,
audioTrackID,
}: {
trackId: HMSTrackID;
videoTrackID?: string;
audioTrackID?: string;
}) => !!trackId && ((!!videoTrackID && videoTrackID === trackId) || (!!audioTrackID && audioTrackID === trackId));
const spacingCSS = { '@md': { my: '$8', fontWeight: '$semiBold', fontSize: 'sm' } };
const SpotlightActions = ({
peerId,
onSpotLightClick = () => {
return;
},
}: {
peerId: string;
onSpotLightClick: () => void;
}) => {
const hmsActions = useHMSActions();
const spotlightPeerId = useHMSStore(selectSessionStore(SESSION_STORE_KEY.SPOTLIGHT));
const isTileSpotlighted = spotlightPeerId === peerId;
const dragClassName = getDragClassName();
const setSpotlightPeerId = (peerIdToSpotlight?: string) =>
hmsActions.sessionStore
.set(SESSION_STORE_KEY.SPOTLIGHT, peerIdToSpotlight)
.catch((err: HMSException) => ToastManager.addToast({ title: err.description }));
return (
{
if (isTileSpotlighted) {
setSpotlightPeerId();
} else {
setSpotlightPeerId(peerId);
}
onSpotLightClick();
}}
>
{isTileSpotlighted ? 'Remove from Spotlight' : 'Spotlight Tile for everyone'}
);
};
const PinActions = ({ audioTrackID, videoTrackID }: { videoTrackID: string; audioTrackID: string }) => {
const [pinnedTrackId, setPinnedTrackId] = useSetAppDataByKey(APP_DATA.pinnedTrackId);
const dragClassName = getDragClassName();
const isTilePinned = isSameTile({
trackId: pinnedTrackId,
videoTrackID,
audioTrackID,
});
return (
<>
(isTilePinned ? setPinnedTrackId() : setPinnedTrackId(videoTrackID || audioTrackID))}
>
{isTilePinned ? 'Unpin' : 'Pin'} Tile for myself
>
);
};
const MinimiseInset = () => {
const [minimised, setMinimised] = useSetAppDataByKey(APP_DATA.minimiseInset);
const dragClassName = getDragClassName();
return (
<>
setMinimised(!minimised)}>
{minimised ? 'Show' : 'Minimise'} your video
>
);
};
const SimulcastLayers = ({ trackId }: { trackId: HMSTrackID }) => {
const track: HMSVideoTrack = useHMSStore(selectTrackByID(trackId)) as HMSVideoTrack;
const actions = useHMSActions();
const bg = useDropdownSelection();
if (!track?.layerDefinitions?.length || track.degraded || !track.enabled) {
return null;
}
const currentLayer = track.layerDefinitions.find((layer: HMSSimulcastLayerDefinition) => layer.layer === track.layer);
const dragClassName = getDragClassName();
return (
Select maximum resolution
{track.layerDefinitions.map((layer: HMSSimulcastLayerDefinition) => {
return (
{
await actions.setPreferredLayer(trackId, layer.layer);
}}
css={{
justifyContent: 'space-between',
bg: track.preferredLayer === layer.layer ? bg : undefined,
'&:hover': {
bg: track.preferredLayer === layer.layer ? bg : undefined,
},
}}
>
{layer.layer}
{layer.resolution.width}x{layer.resolution.height}
);
})}
Currently streaming:
{currentLayer ? (
<>
{track.layer} ({currentLayer.resolution.width}x{currentLayer.resolution.height})
>
) : (
'-'
)}
);
};
export const TileMenuContent = ({
videoTrackID,
audioTrackID,
isLocal,
isScreenshare,
showSpotlight,
showPinAction,
peerID,
canMinimise,
closeSheetOnClick = () => {
return;
},
openNameChangeModal = () => {
return;
},
openRoleChangeModal = () => {
return;
},
}: {
videoTrackID: string;
audioTrackID: string;
isLocal: boolean;
isScreenshare: boolean;
showSpotlight: boolean;
showPinAction: boolean;
peerID: string;
canMinimise?: boolean;
closeSheetOnClick?: () => void;
openNameChangeModal?: () => void;
openRoleChangeModal?: () => void;
}) => {
const actions = useHMSActions();
const dragClassName = getDragClassName();
const permissions = useHMSStore(selectPermissions);
const canChangeRole = !!permissions?.changeRole;
const removeOthers = !!permissions?.removeOthers;
const { userName } = useHMSPrebuiltContext();
const roles = useHMSStore(selectAvailableRoleNames);
const { isAudioEnabled, isVideoEnabled, setVolume, toggleAudio, toggleVideo, volume } = useRemoteAVToggle(
audioTrackID,
videoTrackID,
);
const { sendEvent } = useCustomEvent({
type: REMOTE_STOP_SCREENSHARE_TYPE,
});
const isMobile = useMedia(cssConfig.media.md);
if (isLocal) {
return showPinAction || canMinimise || !userName || showSpotlight ? (
<>
{showPinAction && }
{showSpotlight && closeSheetOnClick()} />}
{canMinimise && }
{!userName && (
{
openNameChangeModal();
closeSheetOnClick();
}}
>
Change Name
)}
>
) : null;
}
return (
<>
{toggleVideo ? (
{
toggleVideo();
closeSheetOnClick();
}}
data-testid={isVideoEnabled ? 'mute_video_participant_btn' : 'unmute_video_participant_btn'}
>
{isVideoEnabled ? : }
{isVideoEnabled ? 'Mute Video' : 'Request to Unmute Video'}
) : null}
{toggleAudio ? (
{
toggleAudio();
closeSheetOnClick();
}}
data-testid={isAudioEnabled ? 'mute_audio_participant_btn' : 'unmute_audio_participant_btn'}
>
{isAudioEnabled ? : }
{isAudioEnabled ? 'Mute Audio' : 'Request to Unmute Audio'}
) : null}
{!isScreenshare && canChangeRole && roles.length > 1 ? (
{
openRoleChangeModal();
closeSheetOnClick();
}}
data-testid="change_role_btn"
>
Switch Role
) : null}
{!isIOS && audioTrackID ? (
Volume ({volume})
setVolume?.(e[0])}
/>
) : null}
{showPinAction && (
<>
{showSpotlight && closeSheetOnClick()} />}
>
)}
{isMobile ? null : }
{removeOthers ? (
{
try {
await actions.removePeer(peerID, '');
} catch (error) {
// TODO: Toast here
}
closeSheetOnClick();
}}
data-testid="remove_participant_btn"
>
Remove Participant
) : null}
{removeOthers && isScreenshare ? (
{
sendEvent({});
closeSheetOnClick();
}}
css={spacingCSS}
>
Stop Screenshare
) : null}
>
);
};