Untitled
plain_text
2 months ago
11 kB
1
Indexable
Never
import { RouteProp } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { ContentHint, StreamKinds, VideoViewer, useDisplayMedia, usePublisher, usePublisherState, useRemoteStreams, useSharedDisplayMedia, useSharedUserMedia, } from 'bluesea-media-react-native-sdk'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Dimensions, TouchableOpacity, View } from 'react-native'; import useAppState from 'react-native-appstate-hook'; import Icon from 'react-native-vector-icons/Ionicons'; import IconM from 'react-native-vector-icons/MaterialCommunityIcons'; import { outgoingAudioIssueEvent } from '../../../App'; import { LOCAL_AUDIO_STREAM_ID, LOCAL_SCREEN_STREAM_ID, LOCAL_VIDEO_STREAM_ID, audio_config, audio_publisher_config, screen_config, screen_publisher_config, video_config, video_publisher_config, } from 'screens/calling/config'; import RNCallKeep from 'react-native-callkeep'; import { RootStackParamList } from 'navigation/types'; import { CallType } from 'contexts/calling/hooks'; import { DataContainer, useReactionState } from 'utils/reaction'; import ViewerItem from './ViewerItem'; import { BlueseaSenders, EBlueseaStreamPriority, Stream } from './types'; import { RemoteBigViewer } from './RemoteBigViewer'; import { usePeerRemoteStreamActive } from 'screens/calling/hooks'; import { Flex, Pressable } from 'native-base'; const { width } = Dimensions.get('window'); const widthButton = Math.min((width - 48 - 48) / 5, 80); type Navigation = NativeStackNavigationProp<RootStackParamList, 'VideoCall'>; type Route = RouteProp<RootStackParamList, 'VideoCall'>; interface IProps { navigation: Navigation; route: Route; exit: () => void; toggle: () => void; } export const CallControlsContainer = ({ route, exit, toggle, navigation }: IProps) => { const [using_speaker, setUsingSpeaker] = useState(false); const { appState } = useAppState(); const call = route.params.call; const is_video_call = call.info.call_type == CallType.Video; const [can_use_mic, setCanUseMic] = useState(true); const [can_use_cam, setCanUseCam] = useState(is_video_call); const mic_outgoing_issue_at = useReactionState(outgoingAudioIssueEvent); const displayMedia = useDisplayMedia(); const [mic_stream, mic_err, switchMicStream] = useSharedUserMedia(LOCAL_AUDIO_STREAM_ID); const [cam_stream, cam_err, switchCamStream] = useSharedUserMedia(LOCAL_VIDEO_STREAM_ID); //const [screenStream, err, screenStreamChanger] = useSharedDisplayMedia(LOCAL_SCREEN_STREAM_ID); const [screenStream, err, screenStreamChanger] = useSharedDisplayMedia(LOCAL_SCREEN_STREAM_ID); const mic_container = useMemo<DataContainer<any>>(() => new DataContainer(null), []); const [prvScreenStream, setPrvScreenStream] = React.useState<any>(null); const mic_publisher = usePublisher(audio_publisher_config); const cam_publisher = usePublisher(video_publisher_config); const screen_publisher = usePublisher({ kind: StreamKinds.VIDEO, name: 'screen_main', stream: screenStream, simulcast: true, screen: true, }); React.useEffect(() => { if (!screenStream) { return; } screen_publisher.switchStream(screenStream); }, [screenStream, screen_publisher]); //const screen_publisher = usePublisher(screen_publisher_config); //const [state_send, screen_pub_stream] = usePublisherState(screen_publisher); const screenVideoPublisher = usePublisher(BlueseaSenders.screen_video); const screenAudioPublisher = usePublisher(audio_publisher_config); //const [userState, setUserState] = useMeetingParticipantState(); const [, mic_pub_stream] = usePublisherState(mic_publisher); const [, cam_pub_stream] = usePublisherState(cam_publisher); const [shareScreen, screenPublisherStream] = usePublisherState(screenVideoPublisher); console.log('Start screenPublisherStream ==================================>'); console.log(screenPublisherStream); console.log('End===========================================================>'); console.log('Start screenStream ==================================>'); console.log(screenStream); console.log('End===========================================================>'); const video_streams = useRemoteStreams(StreamKinds.VIDEO, true); // React.useEffect(() => { // if (!screenStream) { // return; // } // screenAudioPublisher.switchStream(screenStream); // }, [screenAudioPublisher, screenStream]); // React.useEffect(() => { // screenVideoPublisher.switchStream(screenStream); // if (screenStream) { // //setUserState({ ...userState, screenShare: true }); // //sendEvent('screen-share', { screenShare: true }); // } else { // if (prvScreenStream) { // //setUserState({ ...userState, screenShare: false }); // //sendEvent('screen-share', { screenShare: false }); // } // } // }, [ // //currentParticipant.id, // prvScreenStream, // screenStream, // screenVideoPublisher, // // sendEvent, // // setUserState, // // userState, // ]); // For init streams useEffect(() => { switchMicStream(audio_config); RNCallKeep.addEventListener('didChangeAudioRoute', ({ output }) => { setUsingSpeaker(output == 'Speaker' || output == 'SPEAKER'); }); RNCallKeep.addEventListener('didPerformSetMutedCallAction', ({ callUUID, muted }) => { if (muted) { mic_publisher.switchStream(null); } else { mic_publisher.switchStream(mic_container.getValue || null); } }); return () => { RNCallKeep.removeEventListener('didChangeAudioRoute'); RNCallKeep.removeEventListener('didPerformSetMutedCallAction'); }; }, []); const onEndedScreenShare = React.useCallback(() => { screenStreamChanger(undefined); }, []); React.useEffect(() => { screenStream?.stream.getVideoTracks()?.[0]?.addEventListener('ended', onEndedScreenShare); return () => { screenStream?.stream.getVideoTracks()?.[0]?.removeEventListener('ended', onEndedScreenShare); }; }, [screenStream?.stream]); useEffect(() => { if (!!mic_outgoing_issue_at && can_use_mic) { // switchMicStream(audio_config) } }, [mic_outgoing_issue_at, can_use_mic]); useEffect(() => { if (appState == 'active' && can_use_cam) { switchCamStream(video_config); } else { switchCamStream(undefined); } }, [switchCamStream, can_use_cam, appState]); // For control publisher streams useEffect(() => { mic_container.change(mic_stream); mic_publisher.switchStream(mic_stream); }, [mic_stream]); // useEffect(() => { // console.log('screen stream', screenStream); // if (appState == 'active' && !!screenStream) { // screenVideoPublisher.switchStream(screenStream); // // cam_publisher.switchStream(cam_stream); // return () => { // screenVideoPublisher?.switchStream(null); // }; // } // }, [screenVideoPublisher, appState, screenStream]); useEffect(() => { console.log('cam_stream', cam_stream); if (appState == 'active' && !!cam_stream) { cam_publisher.switchStream(cam_stream); return () => { cam_publisher?.switchStream(null); }; } }, [cam_publisher, appState, cam_stream]); const toggleMic = React.useCallback(() => { let new_can_use_mic = !can_use_mic; setCanUseMic(new_can_use_mic); if (mic_publisher) { if (new_can_use_mic) { RNCallKeep.setMutedCall(call.info.call_id, false); mic_publisher.switchStream(mic_stream || null); } else { RNCallKeep.setMutedCall(call.info.call_id, true); mic_publisher.switchStream(null); } } }, [can_use_mic, mic_stream, mic_publisher]); const toggleCam = React.useCallback(() => { setCanUseCam(!can_use_cam); }, [can_use_cam]); const toggleShare = React.useCallback(() => { setPrvScreenStream(screenStream); if (screenPublisherStream) { screenStreamChanger(undefined); } else { screenStreamChanger(screen_config); } }, []); const actions = React.useMemo( () => [ { is_active: !!mic_pub_stream, is_alert: !!mic_err || !!mic_outgoing_issue_at, icon: !!mic_pub_stream ? 'mic-outline' : 'mic-off-outline', onPress: toggleMic, }, { is_active: !!cam_pub_stream, is_alert: false, icon: !!cam_pub_stream ? 'videocam-outline' : 'videocam-off-outline', //icon: 'videocam-outline', onPress: toggleCam, }, { is_active: false, is_alert: false, icon: 'share-outline', onPress: toggleShare, }, { is_active: false, is_alert: false, icon: 'people-outline', onPress: toggle, }, { is_active: false, is_alert: false, icon: 'close-outline', onPress: exit, }, ], [mic_pub_stream, mic_err, mic_outgoing_issue_at, cam_pub_stream, screenPublisherStream] ); return ( <View> {/* {screenStream && ( <VideoViewer objectFit="cover" style={{ width: 'full', height: 300 }} stream={screenStream} priority={1000} /> )} */} <Flex display="flex" flexDirection="row" px="5" position="absolute" w="full" justifyContent="space-between"> {actions.map((item, index) => { const { is_active, is_alert, icon, onPress } = item; return ( <Pressable w={widthButton} h={widthButton} justifyContent="center" alignItems="center" p="1" borderRadius="full" bg={is_active ? 'red' : 'white'} key={index} _pressed={{ opacity: 0.7 }} onPress={onPress}> {is_alert && ( <Icon name="alert-circle" style={{ position: 'absolute', right: 0, top: 0 }} size={30} color={'red'} /> )} {index === actions.length - 1 ? ( <IconM name="phone-hangup" style={{ left: 1 }} size={32} color={is_active ? 'black' : 'white'} /> ) : ( <Icon name={icon} style={{ left: 1 }} size={32} color={is_active ? 'white' : 'black'} /> )} </Pressable> ); })} </Flex> </View> ); };