UNPKG

@100mslive/react-native-room-kit

Version:

100ms Room Kit provides simple & easy to use UI components to build Live Streaming & Video Conferencing experiences in your apps.

318 lines (317 loc) 12.3 kB
import * as React from 'react'; import Modal from 'react-native-modal'; import { StyleSheet, TouchableOpacity, View, Text } from 'react-native'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { HMSTrackType } from '@100mslive/react-native-hms'; import { useHMSInstance, useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; import { setRoleChangeRequest } from '../redux/actions'; import { useHMSActions } from '../hooks-sdk'; import { parseMetadata } from '../utils/functions'; import { NotificationTypes } from '../types'; import { Header } from './Header'; import { selectCanPublishTrackForRole } from '../hooks-sdk-selectors'; import { HMSPrimaryButton } from './HMSPrimaryButton'; import { CameraIcon, MicIcon, RotateCameraIcon } from '../Icons'; import { PressableIcon } from './PressableIcon'; import { AvatarView } from './PeerVideoTile/AvatarView'; import { HMSVideoView } from './HMSVideoView'; import { selectIsHLSViewer, selectLayoutConfigForRole } from '../hooks-util-selectors'; const _PreviewForRoleChangeModal = () => { const dispatch = useDispatch(); const hmsInstance = useHMSInstance(); const hmsActions = useHMSActions(); const roleChangeRequest = useSelector(state => state.hmsStates.roleChangeRequest); const localPeerName = useSelector(state => { var _state$hmsStates$loca; return ((_state$hmsStates$loca = state.hmsStates.localPeer) === null || _state$hmsStates$loca === void 0 ? void 0 : _state$hmsStates$loca.name) || ''; }); const localPeerRoleName = useSelector(state => { var _state$hmsStates$loca2; return (_state$hmsStates$loca2 = state.hmsStates.localPeer) === null || _state$hmsStates$loca2 === void 0 || (_state$hmsStates$loca2 = _state$hmsStates$loca2.role) === null || _state$hmsStates$loca2 === void 0 ? void 0 : _state$hmsStates$loca2.name; }); const localPeerMetadata = useSelector(state => { var _state$hmsStates$loca3; return parseMetadata((_state$hmsStates$loca3 = state.hmsStates.localPeer) === null || _state$hmsStates$loca3 === void 0 ? void 0 : _state$hmsStates$loca3.metadata); }, shallowEqual); const becomeHLSViewer = useSelector(state => { const layoutConfig = selectLayoutConfigForRole(state.hmsStates.layoutConfig, (roleChangeRequest === null || roleChangeRequest === void 0 ? void 0 : roleChangeRequest.suggestedRole) || null); return selectIsHLSViewer(roleChangeRequest === null || roleChangeRequest === void 0 ? void 0 : roleChangeRequest.suggestedRole, layoutConfig); }); const [localVideoTrack, setLocalVideoTrack] = React.useState(null); const [localAudioTrack, setLocalAudioTrack] = React.useState(null); const [isLocalAudioMuted, setIsLocalAudioMuted] = React.useState(); const [isLocalVideoMuted, setIsLocalVideoMuted] = React.useState(); const { background_dim: backgroundDimColor } = useHMSRoomColorPalette(); const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ container: { backgroundColor: theme.palette.background_dim }, footer: { backgroundColor: theme.palette.background_default }, heading: { color: theme.palette.on_surface_high, fontFamily: `${typography.font_family}-SemiBold` }, subheading: { color: theme.palette.on_surface_medium, fontFamily: `${typography.font_family}-Regular` }, cameraRotation: { tintColor: isLocalVideoMuted ? theme.palette.on_surface_low : theme.palette.on_surface_high }, pressableIcon: { borderColor: theme.palette.border_bright }, activePressableIcon: { backgroundColor: theme.palette.surface_brighter, borderColor: theme.palette.surface_brighter }, declineButton: { borderColor: theme.palette.secondary_default }, declineButtonText: { color: theme.palette.on_surface_high, fontFamily: `${typography.font_family}-SemiBold` } }), [isLocalVideoMuted]); const onModalShow = async () => { if (roleChangeRequest && roleChangeRequest.suggestedRole && roleChangeRequest.suggestedRole.name) { // get preview tracks const previewForRoleTracks = await hmsInstance.previewForRole(roleChangeRequest.suggestedRole.name); const localVideoTrack = previewForRoleTracks.find(track => track.type === HMSTrackType.VIDEO); if (localVideoTrack) { localVideoTrack.setMute(false); setLocalVideoTrack(localVideoTrack); setIsLocalVideoMuted(false); } const localAudioTrack = previewForRoleTracks.find(track => track.type === HMSTrackType.AUDIO); if (localAudioTrack) { localAudioTrack.setMute(false); setLocalAudioTrack(localAudioTrack); setIsLocalAudioMuted(false); } // lower hand await hmsActions.lowerLocalPeerHand(); } }; const handleRequestAccept = async () => { dispatch(setRoleChangeRequest(null)); // saving current role in peer metadata, // so that when peer is removed from stage, we can assign previous role to it. if (localPeerRoleName) { const newMetadata = { ...localPeerMetadata, prevRole: localPeerRoleName }; await hmsActions.changeMetadata(newMetadata); } await hmsInstance.acceptRoleChange(); }; const handleRequestDecline = async () => { await hmsInstance.cancelPreview(); if (roleChangeRequest !== null && roleChangeRequest !== void 0 && roleChangeRequest.requestedBy) { await hmsInstance.sendDirectMessage('', roleChangeRequest.requestedBy, NotificationTypes.ROLE_CHANGE_DECLINED); } dispatch(setRoleChangeRequest(null)); }; const handleAudioMuteTogglePress = async () => { if (!localAudioTrack) { return; } const enable = !isLocalAudioMuted; try { setIsLocalAudioMuted(enable); localAudioTrack.setMute(enable); } catch (error) { setIsLocalAudioMuted(!enable); return Promise.reject(error); } }; const handleVideoMuteTogglePress = async () => { if (!localVideoTrack) { return; } const enable = !isLocalVideoMuted; try { setIsLocalVideoMuted(enable); localVideoTrack.setMute(enable); } catch (error) { setIsLocalVideoMuted(!enable); return Promise.reject(error); } }; const handleSwitchCameraPress = async () => { if (isLocalVideoMuted) { return; } if (!localVideoTrack) { return; } localVideoTrack.switchCamera(); }; const canPublishAudio = selectCanPublishTrackForRole(roleChangeRequest === null || roleChangeRequest === void 0 ? void 0 : roleChangeRequest.suggestedRole, 'audio'); const canPublishVideo = selectCanPublishTrackForRole(roleChangeRequest === null || roleChangeRequest === void 0 ? void 0 : roleChangeRequest.suggestedRole, 'video'); const heading = becomeHLSViewer ? "You're invited to view the live stream" : "You're invited to join the stage"; const subheading = getSubheading(canPublishAudio, canPublishVideo); return /*#__PURE__*/React.createElement(Modal, { isVisible: roleChangeRequest !== null, animationIn: 'fadeInUp', animationInTiming: 100, animationOutTiming: 100, animationOut: 'fadeOutDown', backdropColor: backgroundDimColor, backdropOpacity: 0.3, onBackButtonPress: handleRequestDecline, onBackdropPress: handleRequestDecline, onModalShow: onModalShow, useNativeDriver: true, useNativeDriverForBackdrop: true, hideModalContentWhileAnimating: true, style: styles.modal, supportedOrientations: ['portrait', 'landscape'] }, /*#__PURE__*/React.createElement(View, { style: [styles.container, hmsRoomStyles.container] }, /*#__PURE__*/React.createElement(View, { style: [styles.container, hmsRoomStyles.container] }, /*#__PURE__*/React.createElement(AvatarView, { name: localPeerName, avatarStyles: styles.avatar, videoView: localVideoTrack && localVideoTrack.trackId && !isLocalVideoMuted ? /*#__PURE__*/ // && localVideoTrack.isMute() === false // can't rely on `isMute()` result, because we are not receiving ON_TRACK_UPDATES for `previewForRole` tracks React.createElement(HMSVideoView, { trackId: localVideoTrack.trackId }) : null })), /*#__PURE__*/React.createElement(View, { style: styles.header }, /*#__PURE__*/React.createElement(Header, { showControls: false, transparent: true })), /*#__PURE__*/React.createElement(View, { style: styles.footerWrapper }, /*#__PURE__*/React.createElement(View, { style: [styles.footer, hmsRoomStyles.footer] }, /*#__PURE__*/React.createElement(Text, { style: [styles.heading, hmsRoomStyles.heading] }, heading), subheading ? /*#__PURE__*/React.createElement(Text, { style: [styles.subheading, hmsRoomStyles.subheading] }, subheading) : null, canPublishAudio || canPublishVideo ? /*#__PURE__*/React.createElement(View, { style: styles.micAndCameraControls }, canPublishAudio && localAudioTrack ? /*#__PURE__*/React.createElement(PressableIcon, { onPress: handleAudioMuteTogglePress, active: isLocalAudioMuted, style: [styles.pressableIcon, hmsRoomStyles.pressableIcon, !!isLocalAudioMuted ? hmsRoomStyles.activePressableIcon : null] }, /*#__PURE__*/React.createElement(MicIcon, { muted: !!isLocalAudioMuted })) : null, canPublishVideo && localVideoTrack ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, { style: styles.manageLocalVideoWrapper }, /*#__PURE__*/React.createElement(PressableIcon, { onPress: handleVideoMuteTogglePress, active: isLocalVideoMuted, style: [styles.pressableIcon, hmsRoomStyles.pressableIcon, !!isLocalVideoMuted ? hmsRoomStyles.activePressableIcon : null] }, /*#__PURE__*/React.createElement(CameraIcon, { muted: !!isLocalVideoMuted }))), /*#__PURE__*/React.createElement(PressableIcon, { onPress: handleSwitchCameraPress, disabled: isLocalVideoMuted, style: [styles.pressableIcon, hmsRoomStyles.pressableIcon] }, /*#__PURE__*/React.createElement(RotateCameraIcon, { style: hmsRoomStyles.cameraRotation }))) : null) : null, /*#__PURE__*/React.createElement(HMSPrimaryButton, { loading: false, onPress: handleRequestAccept, title: "Join Now", style: styles.joinButton }), /*#__PURE__*/React.createElement(TouchableOpacity, { style: [styles.declineButton, hmsRoomStyles.declineButton], onPress: handleRequestDecline }, /*#__PURE__*/React.createElement(Text, { style: [styles.declineButtonText, hmsRoomStyles.declineButtonText] }, "Decline")))))); }; export const PreviewForRoleChangeModal = /*#__PURE__*/React.memo(_PreviewForRoleChangeModal); const styles = StyleSheet.create({ modal: { margin: 0 }, container: { flex: 1, position: 'relative' }, header: { position: 'absolute', width: '100%' }, micAndCameraControls: { flexDirection: 'row' }, manageLocalVideoWrapper: { marginHorizontal: 16 }, footerWrapper: { position: 'absolute', bottom: 0, width: '100%', zIndex: 30 }, footer: { flex: 1, borderTopLeftRadius: 16, borderTopRightRadius: 16, paddingHorizontal: 16, paddingTop: 24, paddingBottom: 32 }, heading: { fontSize: 20, lineHeight: 24, letterSpacing: 0.15, marginBottom: 8 }, subheading: { fontSize: 14, lineHeight: 20, letterSpacing: 0.25, marginBottom: 24 }, pressableIcon: { backgroundColor: undefined, borderWidth: 1 }, avatar: { marginBottom: 200 }, joinButton: { marginTop: 16 }, declineButton: { flex: 1, paddingVertical: 8, paddingHorizontal: 16, borderRadius: 8, borderWidth: 1, marginTop: 16 }, declineButtonText: { fontSize: 16, lineHeight: 24, letterSpacing: 0.5, textAlign: 'center' } }); const getSubheading = (canPublishAudio, canPublishVideo) => { if (canPublishAudio && canPublishVideo) { return 'Setup your audio and video before joining'; } if (canPublishAudio) { return 'Setup your audio before joining'; } if (canPublishVideo) { return 'Setup your video before joining'; } return ''; }; //# sourceMappingURL=PreviewForRoleChangeModal.js.map