@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
JavaScript
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