UNPKG

@100mslive/roomkit-react

Version:

![Banner](https://github.com/100mslive/web-sdks/blob/06c65259912db6ccd8617f2ecb6fef51429251ec/prebuilt-banner.png)

197 lines (189 loc) 5.86 kB
import React from 'react'; import { DeviceType, getAudioDeviceCategory, HMSAudioDeviceCategory, selectIsLocalVideoEnabled, selectLocalVideoTrackID, selectVideoTrackByID, useDevices, useHMSActions, useHMSStore, } from '@100mslive/react-sdk'; import { BluetoothIcon, CameraFlipIcon, CheckIcon, CrossIcon, HeadphonesIcon, SpeakerIcon, TelePhoneIcon, } from '@100mslive/react-icons'; import { HorizontalDivider } from '../../../Divider'; import { Label } from '../../../Label'; import { Box, Flex } from '../../../Layout'; import { Sheet } from '../../../Sheet'; import { Text } from '../../../Text'; import IconButton from '../../IconButton'; import { ToastManager } from '../Toast/ToastManager'; export const CamaraFlipActions = () => { const actions = useHMSActions(); const { allDevices } = useDevices(); const { videoInput } = allDevices; const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); const videoTrackId = useHMSStore(selectLocalVideoTrackID); const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId)); if (!videoInput || !videoInput?.length || !localVideoTrack?.facingMode) { return null; } return ( <Box> <IconButton disabled={!isVideoOn} onClick={async () => { try { await actions.switchCamera(); } catch (e) { ToastManager.addToast({ title: `Error while flipping camera ${e.message || ''}`, variant: 'error', }); } }} > <CameraFlipIcon /> </IconButton> </Box> ); }; // It will handle and show audio input devices in Mweb while audio output devices in desktop export const AudioActions = () => { const { allDevices, selectedDeviceIDs, updateDevice } = useDevices(); // don't show speaker selector where the API is not supported, and use // a generic word("Audio") for Mic. In some cases(Chrome Android for example) this changes both mic and speaker keeping them in sync. const shouldShowAudioOutput = 'setSinkId' in HTMLMediaElement.prototype; const { audioInput, audioOutput } = allDevices; let availableAudioDevices = audioInput; let selectedAudio = selectedDeviceIDs.audioInput; if (shouldShowAudioOutput) { availableAudioDevices = audioOutput; selectedAudio = selectedDeviceIDs.audioOutput; } const hmsActions = useHMSActions(); const audioFiltered = availableAudioDevices?.find(item => !!item.label); const currentSelection = availableAudioDevices?.find(item => item.deviceId === selectedAudio); if (!audioFiltered) { return null; } const deviceCategory = getAudioDeviceCategory(currentSelection?.label); let AudioIcon = <SpeakerIcon />; if (deviceCategory === HMSAudioDeviceCategory.BLUETOOTH) { AudioIcon = <BluetoothIcon />; } else if (deviceCategory === HMSAudioDeviceCategory.WIRED) { AudioIcon = <HeadphonesIcon />; } else if (deviceCategory === HMSAudioDeviceCategory.EARPIECE) { AudioIcon = <TelePhoneIcon />; } return ( <AudioSelectionSheet audioDevices={availableAudioDevices} audioSelected={selectedAudio} onChange={async deviceId => { try { await updateDevice({ deviceId, deviceType: shouldShowAudioOutput ? DeviceType.audioOutput : DeviceType.audioInput, }); } catch (e) { ToastManager.addToast({ title: `Error while changing audio device ${e.message || ''}`, variant: 'error', }); } }} > <Box onClick={async () => { // refresh device as `devicechange` listener won't work in mobile device await hmsActions.refreshDevices(); }} > <IconButton>{AudioIcon}</IconButton> </Box> </AudioSelectionSheet> ); }; const AudioSelectionSheet = ({ audioDevices, audioSelected, onChange, children }) => { return ( <Sheet.Root> <Sheet.Trigger asChild>{children}</Sheet.Trigger> <Sheet.Content> <Sheet.Title css={{ py: '$10', px: '$8', alignItems: 'center' }}> <Flex direction="row" justify="between" css={{ w: '100%' }}> <Text variant="h6" css={{ display: 'flex' }}> Audio </Text> <Sheet.Close> <IconButton as="div" data-testid="dialog_cross_icon"> <CrossIcon /> </IconButton> </Sheet.Close> </Flex> </Sheet.Title> <HorizontalDivider /> <Flex direction="column" css={{ px: '$8', maxHeight: '80vh', overflowY: 'auto', }} > {audioDevices.map(audioDevice => { return ( <SelectWithLabel key={audioDevice.deviceId} label={audioDevice.label} id={audioDevice.deviceId} checked={audioDevice.deviceId === audioSelected} onChange={() => onChange(audioDevice.deviceId)} /> ); })} </Flex> </Sheet.Content> </Sheet.Root> ); }; const SelectWithLabel = ({ label, icon = <></>, checked, id, onChange }) => { return ( <Flex align="center" css={{ my: '$2', py: '$8', w: '100%', borderBottom: '1px solid $border_default', }} onClick={onChange} > <Label htmlFor={id} css={{ fontSize: '$md', fontWeight: '$semiBold', color: '$on_surface_high', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '$8', flex: '1 1 0', }} > {icon} {label} </Label> {checked && <CheckIcon width={24} height={24} />} </Flex> ); };