Guest User

Untitled

a guest
Sep 7th, 2020
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     import React, { useRef, useState, useEffect } from 'react';
  2. import {
  3.   SafeAreaView,
  4.   StatusBar,
  5.   Platform,
  6.   View,
  7.   TouchableOpacity,
  8.   StyleSheet,
  9. } from 'react-native';
  10. import ConnectyCube from 'react-native-connectycube';
  11. import InCallManager from 'react-native-incall-manager';
  12. import RNCallKeep from 'react-native-callkeep';
  13. import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
  14. import { v4 as uuid } from 'uuid';
  15. import VideoScreen from './video_screen';
  16. import UsersSelect from './users_select';
  17. import {
  18.   Session,
  19.   Stream,
  20.   Listener,
  21.   users,
  22.   Extension,
  23.   Track,
  24.   MEDIA_OPTIONS,
  25.   SETUP_OPTIONS,
  26. } from '../config';
  27. import useStateCallback from '../../components/common/hooks/state_callback';
  28.  
  29. const isIOS = Platform.OS === 'ios';
  30.  
  31. const CallControl = ({ route }: { route: any }) => {
  32.   const initSession = {
  33.     ID: '',
  34.     initiatorID: 0,
  35.     currentUserID: 0,
  36.     opponentsIDs: [],
  37.     getUserMedia: () => {},
  38.     accept: () => {},
  39.     call: () => {},
  40.     stop: () => {},
  41.     mute: () => {},
  42.     unmute: () => {},
  43.     reject: () => {},
  44.   };
  45.   const initExtension = { busy: false };
  46.  
  47.   const sess = useRef<Session>(initSession);
  48.   const ext = useRef<Extension>(initExtension);
  49.   const callId = useRef<string>('');
  50.   const currentUser = route?.params?.currentUser || {};
  51.  
  52.   const [localStream, setLocalStreams] = useState<any>([]);
  53.   const [remoteStreams, setRemoteStreams] = useStateCallback<
  54.     [] | Array<Stream>
  55.   >([]);
  56.  
  57.   const [selectedUserId, setSelectedUser] = useState<null | number>(null);
  58.  
  59.   const [isAudioMuted, setIsAudioMuted] = useState(false);
  60.   const [isFrontCamera, setIsFrontCamera] = useState(true);
  61.  
  62.   const cam = true;
  63.  
  64.   const reset = async () => {
  65.     const id = oneTimeId();
  66.     RNCallKeep.endCall(id);
  67.     await ConnectyCube.videochat.clearSession(sess.current.ID);
  68.     RNCallKeep.endAllCalls();
  69.  
  70.     InCallManager.stop();
  71.     setRemoteStreams([]);
  72.     setLocalStreams([]);
  73.     setSelectedUser(null);
  74.     setIsAudioMuted(false);
  75.     setIsFrontCamera(true);
  76.     sess.current = initSession;
  77.     ext.current = initExtension;
  78.     callId.current = '';
  79.   };
  80.  
  81.   const oneTimeId = () => {
  82.     callId.current = callId.current || uuid();
  83.     return callId.current;
  84.   };
  85.  
  86.   // Start/Stop onPress call handlers
  87.   const startCall = async () => {
  88.     if (!selectedUserId) {
  89.       return;
  90.     }
  91.  
  92.     const t = ConnectyCube.videochat.CallType.VIDEO; // AUDIO is also possible
  93.     sess.current = ConnectyCube.videochat.createNewSession([selectedUserId], t);
  94.  
  95.     const stream = await sess.current?.getUserMedia?.(MEDIA_OPTIONS);
  96.     await sess.current?.call({});
  97.  
  98.     setLocalStreams([{ userId: 'localStream', stream }]);
  99.     setRemoteStreams([{ userId: selectedUserId, stream: null }]);
  100.  
  101.     if (isIOS) {
  102.       const id = oneTimeId();
  103.       const name = users.find(u => u.id === selectedUserId)?.name || '';
  104.       RNCallKeep.startCall(id, name, name, 'generic', cam);
  105.     }
  106.   };
  107.  
  108.   const stopCall = async () => {
  109.     await sess.current?.stop?.({});
  110.     await reset();
  111.   };
  112.  
  113.   // CallKeep button actions
  114.   const acceptCall = async () => {
  115.     const id = oneTimeId();
  116.     RNCallKeep.setCurrentCallActive(id);
  117.  
  118.     const stream = await sess.current?.getUserMedia?.(MEDIA_OPTIONS);
  119.     await sess.current?.accept?.({});
  120.  
  121.     setLocalStreams([{ userId: 'localStream', stream }]);
  122.     setRemoteStreams([{ userId: selectedUserId, stream: null }]);
  123.   };
  124.  
  125.   const rejectCall = async () => {
  126.     await sess.current?.reject?.(ext.current);
  127.     await reset();
  128.   };
  129.  
  130.   // ConnectyCall Listeners
  131.   const onCallListener: Listener = async (session, _userId, extension) => {
  132.     ext.current = extension || initExtension;
  133.     sess.current = session || initSession;
  134.  
  135.     const name =
  136.       users.find(u => u.id === sess?.current?.initiatorID)?.name || '';
  137.     const id = oneTimeId();
  138.     RNCallKeep.displayIncomingCall(id, name, name, 'generic', cam);
  139.   };
  140.  
  141.   const onAcceptCallListener: Listener = async (session, _, extension) => {
  142.     ext.current = extension || initExtension;
  143.     sess.current = session || initSession;
  144.   };
  145.  
  146.   const onRemoteStreamListener = async (
  147.     _session: Session,
  148.     userId: number,
  149.     stream: Stream
  150.   ) =>
  151.     setRemoteStreams([...remoteStreams, { userId, stream }], () => {
  152.       InCallManager.start({ media: 'video', auto: false });
  153.       InCallManager.setSpeakerphoneOn(true);
  154.       RNCallKeep.backToForeground();
  155.     });
  156.  
  157.   const onRejectCallListener = async () => {
  158.     await reset();
  159.   };
  160.  
  161.   const onStopCallListener = async () => {
  162.     await reset();
  163.   };
  164.  
  165.   const onUserNotAnswerListener = async () => {
  166.     if (!remoteStreams[0]) {
  167.       await reset();
  168.     }
  169.   };
  170.  
  171.   // Init
  172.   const initializeConnectyCube = () => {
  173.     ConnectyCube.videochat.onCallListener = onCallListener;
  174.     ConnectyCube.videochat.onAcceptCallListener = onAcceptCallListener;
  175.     ConnectyCube.videochat.onRemoteStreamListener = onRemoteStreamListener;
  176.     ConnectyCube.videochat.onRejectCallListener = onRejectCallListener;
  177.     ConnectyCube.videochat.onStopCallListener = onStopCallListener;
  178.     ConnectyCube.videochat.onUserNotAnswerListener = onUserNotAnswerListener;
  179.   };
  180.  
  181.   const initializeCallKeep = async () => {
  182.     await RNCallKeep.setup(SETUP_OPTIONS);
  183.     RNCallKeep.setAvailable(true);
  184.     RNCallKeep.addEventListener('answerCall', acceptCall);
  185.     RNCallKeep.addEventListener('endCall', rejectCall);
  186.   };
  187.  
  188.   const cleanup = () => {
  189.     RNCallKeep.removeEventListener('answerCall');
  190.     RNCallKeep.removeEventListener('endCall');
  191.     stopCall();
  192.   };
  193.  
  194.   useEffect(() => {
  195.     initializeConnectyCube();
  196.     initializeCallKeep();
  197.     return cleanup;
  198.   }, []);
  199.  
  200.   // Actions
  201.   const toggleMute = () => {
  202.     const mute = !isAudioMuted;
  203.     setIsAudioMuted(mute);
  204.     mute ? sess.current?.mute?.('audio') : sess.current?.unmute?.('audio');
  205.   };
  206.  
  207.   const toggleCamera = () => {
  208.     setIsFrontCamera(!isFrontCamera);
  209.     localStream[0]?.stream
  210.       ?.getVideoTracks?.()
  211.       .forEach((track: Track) => track._switchCamera());
  212.   };
  213.  
  214.   // Buttons
  215.   const renderCallStartStopButton = () => (
  216.     <TouchableOpacity
  217.       style={[
  218.         styles.buttonContainer,
  219.         remoteStreams[0] ? styles.buttonCallEnd : styles.buttonCall,
  220.       ]}
  221.       onPress={remoteStreams[0] ? stopCall : startCall}>
  222.       <MaterialIcon
  223.         name={remoteStreams[0] ? 'call-end' : 'call'}
  224.         size={32}
  225.         color='white'
  226.       />
  227.     </TouchableOpacity>
  228.   );
  229.  
  230.   const renderMuteButton = () => (
  231.     <TouchableOpacity
  232.       style={[styles.buttonContainer, styles.buttonMute]}
  233.       onPress={toggleMute}>
  234.       <MaterialIcon
  235.         name={isAudioMuted ? 'mic-off' : 'mic'}
  236.         size={32}
  237.         color='white'
  238.       />
  239.     </TouchableOpacity>
  240.   );
  241.  
  242.   const renderSwitchVideoSourceButton = () => (
  243.     <TouchableOpacity
  244.       style={[styles.buttonContainer, styles.buttonSwitch]}
  245.       onPress={toggleCamera}>
  246.       <MaterialIcon
  247.         name={isFrontCamera ? 'camera-rear' : 'camera-front'}
  248.         size={32}
  249.         color='white'
  250.       />
  251.     </TouchableOpacity>
  252.   );
  253.  
  254.   return (
  255.     <SafeAreaView style={{ flex: 1, backgroundColor: 'black' }}>
  256.       <StatusBar backgroundColor='black' barStyle='light-content' />
  257.       {remoteStreams[0] ? (
  258.         <View style={styles.inColumn}>
  259.           <VideoScreen
  260.             mirror={false}
  261.             stream={remoteStreams?.[0]?.stream}
  262.             userId={remoteStreams?.[0]?.userId}
  263.           />
  264.           <VideoScreen
  265.             mirror={isFrontCamera}
  266.             stream={localStream?.[0]?.stream}
  267.             userId={localStream?.[0]?.userId}
  268.           />
  269.         </View>
  270.       ) : (
  271.         <UsersSelect
  272.           currentUser={currentUser}
  273.           selectedUserId={selectedUserId}
  274.           setSelectedUser={setSelectedUser}
  275.         />
  276.       )}
  277.       <SafeAreaView style={styles.container}>
  278.         <View style={styles.toolBarItem}>
  279.           {remoteStreams[0] && renderMuteButton()}
  280.         </View>
  281.         {(selectedUserId || remoteStreams[0]) && (
  282.           <View style={styles.toolBarItem}>{renderCallStartStopButton()}</View>
  283.         )}
  284.         <View style={styles.toolBarItem}>
  285.           {remoteStreams[0] && localStream && renderSwitchVideoSourceButton()}
  286.         </View>
  287.       </SafeAreaView>
  288.     </SafeAreaView>
  289.   );
  290. };
  291.  
  292. const styles = StyleSheet.create({
  293.   container: {
  294.     position: 'absolute',
  295.     bottom: 20,
  296.     left: 0,
  297.     right: 0,
  298.     height: 60,
  299.     flex: 1,
  300.     justifyContent: 'center',
  301.     flexDirection: 'row',
  302.     zIndex: 100,
  303.   },
  304.   toolBarItem: {
  305.     flex: 1,
  306.     justifyContent: 'center',
  307.     alignItems: 'center',
  308.   },
  309.   buttonContainer: {
  310.     height: 50,
  311.     width: 50,
  312.     borderRadius: 25,
  313.     marginHorizontal: 25,
  314.     justifyContent: 'center',
  315.     alignItems: 'center',
  316.   },
  317.   buttonCall: {
  318.     backgroundColor: 'green',
  319.   },
  320.   buttonCallEnd: {
  321.     backgroundColor: 'red',
  322.   },
  323.   buttonMute: {
  324.     backgroundColor: 'blue',
  325.   },
  326.   buttonSwitch: {
  327.     backgroundColor: 'orange',
  328.   },
  329.   inColumn: {
  330.     flex: 1,
  331.     flexDirection: 'column',
  332.   },
  333. });
  334.  
  335. export default CallControl;
  336.  
Advertisement
Add Comment
Please, Sign In to add comment