Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useRef, useState, useEffect } from 'react';
- import {
- SafeAreaView,
- StatusBar,
- Platform,
- View,
- TouchableOpacity,
- StyleSheet,
- } from 'react-native';
- import ConnectyCube from 'react-native-connectycube';
- import InCallManager from 'react-native-incall-manager';
- import RNCallKeep from 'react-native-callkeep';
- import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
- import { v4 as uuid } from 'uuid';
- import VideoScreen from './video_screen';
- import UsersSelect from './users_select';
- import {
- Session,
- Stream,
- Listener,
- users,
- Extension,
- Track,
- MEDIA_OPTIONS,
- SETUP_OPTIONS,
- } from '../config';
- import useStateCallback from '../../components/common/hooks/state_callback';
- const isIOS = Platform.OS === 'ios';
- const CallControl = ({ route }: { route: any }) => {
- const initSession = {
- ID: '',
- initiatorID: 0,
- currentUserID: 0,
- opponentsIDs: [],
- getUserMedia: () => {},
- accept: () => {},
- call: () => {},
- stop: () => {},
- mute: () => {},
- unmute: () => {},
- reject: () => {},
- };
- const initExtension = { busy: false };
- const sess = useRef<Session>(initSession);
- const ext = useRef<Extension>(initExtension);
- const callId = useRef<string>('');
- const currentUser = route?.params?.currentUser || {};
- const [localStream, setLocalStreams] = useState<any>([]);
- const [remoteStreams, setRemoteStreams] = useStateCallback<
- [] | Array<Stream>
- >([]);
- const [selectedUserId, setSelectedUser] = useState<null | number>(null);
- const [isAudioMuted, setIsAudioMuted] = useState(false);
- const [isFrontCamera, setIsFrontCamera] = useState(true);
- const cam = true;
- const reset = async () => {
- const id = oneTimeId();
- RNCallKeep.endCall(id);
- await ConnectyCube.videochat.clearSession(sess.current.ID);
- RNCallKeep.endAllCalls();
- InCallManager.stop();
- setRemoteStreams([]);
- setLocalStreams([]);
- setSelectedUser(null);
- setIsAudioMuted(false);
- setIsFrontCamera(true);
- sess.current = initSession;
- ext.current = initExtension;
- callId.current = '';
- };
- const oneTimeId = () => {
- callId.current = callId.current || uuid();
- return callId.current;
- };
- // Start/Stop onPress call handlers
- const startCall = async () => {
- if (!selectedUserId) {
- return;
- }
- const t = ConnectyCube.videochat.CallType.VIDEO; // AUDIO is also possible
- sess.current = ConnectyCube.videochat.createNewSession([selectedUserId], t);
- const stream = await sess.current?.getUserMedia?.(MEDIA_OPTIONS);
- await sess.current?.call({});
- setLocalStreams([{ userId: 'localStream', stream }]);
- setRemoteStreams([{ userId: selectedUserId, stream: null }]);
- if (isIOS) {
- const id = oneTimeId();
- const name = users.find(u => u.id === selectedUserId)?.name || '';
- RNCallKeep.startCall(id, name, name, 'generic', cam);
- }
- };
- const stopCall = async () => {
- await sess.current?.stop?.({});
- await reset();
- };
- // CallKeep button actions
- const acceptCall = async () => {
- const id = oneTimeId();
- RNCallKeep.setCurrentCallActive(id);
- const stream = await sess.current?.getUserMedia?.(MEDIA_OPTIONS);
- await sess.current?.accept?.({});
- setLocalStreams([{ userId: 'localStream', stream }]);
- setRemoteStreams([{ userId: selectedUserId, stream: null }]);
- };
- const rejectCall = async () => {
- await sess.current?.reject?.(ext.current);
- await reset();
- };
- // ConnectyCall Listeners
- const onCallListener: Listener = async (session, _userId, extension) => {
- ext.current = extension || initExtension;
- sess.current = session || initSession;
- const name =
- users.find(u => u.id === sess?.current?.initiatorID)?.name || '';
- const id = oneTimeId();
- RNCallKeep.displayIncomingCall(id, name, name, 'generic', cam);
- };
- const onAcceptCallListener: Listener = async (session, _, extension) => {
- ext.current = extension || initExtension;
- sess.current = session || initSession;
- };
- const onRemoteStreamListener = async (
- _session: Session,
- userId: number,
- stream: Stream
- ) =>
- setRemoteStreams([...remoteStreams, { userId, stream }], () => {
- InCallManager.start({ media: 'video', auto: false });
- InCallManager.setSpeakerphoneOn(true);
- RNCallKeep.backToForeground();
- });
- const onRejectCallListener = async () => {
- await reset();
- };
- const onStopCallListener = async () => {
- await reset();
- };
- const onUserNotAnswerListener = async () => {
- if (!remoteStreams[0]) {
- await reset();
- }
- };
- // Init
- const initializeConnectyCube = () => {
- ConnectyCube.videochat.onCallListener = onCallListener;
- ConnectyCube.videochat.onAcceptCallListener = onAcceptCallListener;
- ConnectyCube.videochat.onRemoteStreamListener = onRemoteStreamListener;
- ConnectyCube.videochat.onRejectCallListener = onRejectCallListener;
- ConnectyCube.videochat.onStopCallListener = onStopCallListener;
- ConnectyCube.videochat.onUserNotAnswerListener = onUserNotAnswerListener;
- };
- const initializeCallKeep = async () => {
- await RNCallKeep.setup(SETUP_OPTIONS);
- RNCallKeep.setAvailable(true);
- RNCallKeep.addEventListener('answerCall', acceptCall);
- RNCallKeep.addEventListener('endCall', rejectCall);
- };
- const cleanup = () => {
- RNCallKeep.removeEventListener('answerCall');
- RNCallKeep.removeEventListener('endCall');
- stopCall();
- };
- useEffect(() => {
- initializeConnectyCube();
- initializeCallKeep();
- return cleanup;
- }, []);
- // Actions
- const toggleMute = () => {
- const mute = !isAudioMuted;
- setIsAudioMuted(mute);
- mute ? sess.current?.mute?.('audio') : sess.current?.unmute?.('audio');
- };
- const toggleCamera = () => {
- setIsFrontCamera(!isFrontCamera);
- localStream[0]?.stream
- ?.getVideoTracks?.()
- .forEach((track: Track) => track._switchCamera());
- };
- // Buttons
- const renderCallStartStopButton = () => (
- <TouchableOpacity
- style={[
- styles.buttonContainer,
- remoteStreams[0] ? styles.buttonCallEnd : styles.buttonCall,
- ]}
- onPress={remoteStreams[0] ? stopCall : startCall}>
- <MaterialIcon
- name={remoteStreams[0] ? 'call-end' : 'call'}
- size={32}
- color='white'
- />
- </TouchableOpacity>
- );
- const renderMuteButton = () => (
- <TouchableOpacity
- style={[styles.buttonContainer, styles.buttonMute]}
- onPress={toggleMute}>
- <MaterialIcon
- name={isAudioMuted ? 'mic-off' : 'mic'}
- size={32}
- color='white'
- />
- </TouchableOpacity>
- );
- const renderSwitchVideoSourceButton = () => (
- <TouchableOpacity
- style={[styles.buttonContainer, styles.buttonSwitch]}
- onPress={toggleCamera}>
- <MaterialIcon
- name={isFrontCamera ? 'camera-rear' : 'camera-front'}
- size={32}
- color='white'
- />
- </TouchableOpacity>
- );
- return (
- <SafeAreaView style={{ flex: 1, backgroundColor: 'black' }}>
- <StatusBar backgroundColor='black' barStyle='light-content' />
- {remoteStreams[0] ? (
- <View style={styles.inColumn}>
- <VideoScreen
- mirror={false}
- stream={remoteStreams?.[0]?.stream}
- userId={remoteStreams?.[0]?.userId}
- />
- <VideoScreen
- mirror={isFrontCamera}
- stream={localStream?.[0]?.stream}
- userId={localStream?.[0]?.userId}
- />
- </View>
- ) : (
- <UsersSelect
- currentUser={currentUser}
- selectedUserId={selectedUserId}
- setSelectedUser={setSelectedUser}
- />
- )}
- <SafeAreaView style={styles.container}>
- <View style={styles.toolBarItem}>
- {remoteStreams[0] && renderMuteButton()}
- </View>
- {(selectedUserId || remoteStreams[0]) && (
- <View style={styles.toolBarItem}>{renderCallStartStopButton()}</View>
- )}
- <View style={styles.toolBarItem}>
- {remoteStreams[0] && localStream && renderSwitchVideoSourceButton()}
- </View>
- </SafeAreaView>
- </SafeAreaView>
- );
- };
- const styles = StyleSheet.create({
- container: {
- position: 'absolute',
- bottom: 20,
- left: 0,
- right: 0,
- height: 60,
- flex: 1,
- justifyContent: 'center',
- flexDirection: 'row',
- zIndex: 100,
- },
- toolBarItem: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
- buttonContainer: {
- height: 50,
- width: 50,
- borderRadius: 25,
- marginHorizontal: 25,
- justifyContent: 'center',
- alignItems: 'center',
- },
- buttonCall: {
- backgroundColor: 'green',
- },
- buttonCallEnd: {
- backgroundColor: 'red',
- },
- buttonMute: {
- backgroundColor: 'blue',
- },
- buttonSwitch: {
- backgroundColor: 'orange',
- },
- inColumn: {
- flex: 1,
- flexDirection: 'column',
- },
- });
- export default CallControl;
Advertisement
Add Comment
Please, Sign In to add comment