UNPKG

react-native-classroom

Version:

React Native Class room

451 lines (414 loc) 13.1 kB
/* eslint-disable no-undef */ import React, { Component } from 'react'; import { ScrollView, Alert } from 'react-native'; import { OpenViduReactNativeAdapter, OpenVidu, } from 'openvidu-react-native-adapter'; import axios from 'axios'; import ItemConference from './ItemConference'; export default class OpenViduConference extends Component { constructor(props) { super(props); const ovReact = new OpenViduReactNativeAdapter(); ovReact.initialize(); this.state = { myUserName: props.kidInfo.fullnameStudent, session: undefined, mainStreamManager: undefined, subscribers: [], role: 'PUBLISHER', mirror: true, videoSource: undefined, video: true, audio: true, }; } getToken = async ( mySessionId, OPENVIDU_SERVER_URL, OPENVIDU_SERVER_SECRET, ) => { try { const sessionId_1 = await this.createSession( mySessionId, OPENVIDU_SERVER_URL, OPENVIDU_SERVER_SECRET, ); const token = await this.createToken( sessionId_1, OPENVIDU_SERVER_URL, OPENVIDU_SERVER_SECRET, ); this.initConference(token); } catch (error) { return console.log(error); } }; createSession = (sessionId, OPENVIDU_SERVER_URL, OPENVIDU_SERVER_SECRET) => { return new Promise((resolve) => { const data = JSON.stringify({ customSessionId: sessionId }); axios .post(`${OPENVIDU_SERVER_URL}/openvidu/api/sessions`, data, { headers: { Authorization: `Basic ${btoa( `OPENVIDUAPP:${OPENVIDU_SERVER_SECRET}`, )}`, 'Content-Type': 'application/json', Accept: 'application/json', }, }) .then((response) => { // console.log(`SESSION ${response.data.id} CREATED`); resolve(response.data.id); }) .catch((response) => { // console.log(response); const error = { ...response }; if (!error.response) { console.error('Network error: ', error); if (error.request && error.request._response) { console.error( 'Response of the request: ', error.request._response, ); } Alert.alert('Create Session', error.message || 'Network Error!'); } else if ( error.response && error.response.status && error.response.status === 409 ) { // console.log('RESOLVING WITH SESSIONID, 409'); resolve(sessionId); } else { const msg = `No connection to OpenVidu Server. This may be a certificate error at ${OPENVIDU_SERVER_URL}`; console.warn(msg); Alert.alert( 'No connection to OpenVidu Server.', `This may be a certificate error at "${OPENVIDU_SERVER_URL}"\n\nClick OK to navigate and accept it. ` + `If no certificate warning is shown, then check that your OpenVidu Server is up and running at "${OPENVIDU_SERVER_URL}"`, [ { text: 'Cancel', // onPress: () => hideCotrolAndroid(), style: 'cancel', }, { text: 'OK', // onPress: () => hideCotrolAndroid(), }, ], { cancelable: false }, ); } }); }); }; createToken = (sessionId, OPENVIDU_SERVER_URL, OPENVIDU_SERVER_SECRET) => { return new Promise((resolve, reject) => { const data = JSON.stringify({}); axios .post( `${OPENVIDU_SERVER_URL}/openvidu/api/sessions/${sessionId}/connection`, data, { headers: { Authorization: `Basic ${btoa( `OPENVIDUAPP:${OPENVIDU_SERVER_SECRET}`, )}`, 'Content-Type': 'application/json', }, }, ) .then((response) => { // console.log('TOKEN CREATED: ', response.data.token); resolve(response.data.token); }) .catch((error) => { // console.error(error); reject(error); Alert.alert('Create token', error.message); }); }); }; initConference(token) { const { isObserve, isConnected, kidInfo } = this.props; this.OV = new OpenVidu(); this.setState({ session: this.OV.initSession() }, async () => { const mySession = this.state.session; mySession.on('streamCreated', async (event) => { // console.log(121, 'ADD STREAM ', event); await this.addSubscriber(mySession, event); }); mySession.on('streamDestroyed', (event) => { // console.log(110, 'REMOVE STREAM', event); event.preventDefault(); this.deleteSubscriber(event.stream); }); mySession.on('streamPropertyChanged', (event) => { // console.log(140, event); const { subscribers } = this.state; subscribers.map((item) => { if (item.stream.streamId === event.stream.streamId) { item.stream = event.stream; } return item; }); this.setState({ subscribers }); }); mySession.on('reconnecting', () => {}); mySession.on('reconnected', () => { // this.eventReconnected(); }); mySession.once('sessionDisconnected', (event) => { if (event.reason === 'networkDisconnect') { Alert.alert( 'Disconnected', 'Network Error', // [ // { text: 'Ok', onPress: () => hideCotrolAndroid() }, // ] ); } }); try { const metadata = { clientData: kidInfo.fullnameStudent, role: isObserve ? 'PARENT' : 'STUDENT', name: kidInfo.nickname || kidInfo.fullnameStudent, userId: kidInfo.id, }; mySession .connect(token, metadata) .then(async () => { if (isConnected) { isConnected(true); } if (this.state.role !== 'SUBSCRIBER' && !isObserve) { const properties = { audioSource: undefined, // The source of audio. If undefined default microphone videoSource: undefined, // The source of video. If undefined default webcam publishAudio: true, // Whether you want to start publishing with your audio unmuted or not publishVideo: true, // Whether you want to start publishing with your video enabled or not resolution: '640x480', frameRate: 30, insertMode: 'APPEND', }; const publisher = await this.OV.initPublisherAsync( undefined, properties, ); if (publisher) { this.setState( { mainStreamManager: publisher, videoSource: !properties.videoSource ? '1' : properties.videoSource, // 0: back camera | 1: user camera | }, async () => { mySession.publish(publisher); }, ); } else { this.showError('OpenVidu Error not publisher'); // logSentryOther( // 'OpenVidu Error not publisher', // publisher, // this.props.classId || 0, // ); } } }) .catch(async (err) => { this.showError(err); }); } catch (error) { this.showError(error); } }); } showError = (error) => { const { classId, reconnect } = this.props; // logSentryOther('OpenVidu Connect Error', error, classId); Alert.alert('Error', error.message || 'OpenVidu Connect Error', [ { text: 'Cancel' }, { text: 'Retry', onPress: () => { // hideCotrolAndroid(); if (reconnect) { reconnect(); } }, }, ]); }; splitData = (data) => { const splitData = data.split('%/%'); if (splitData.length > 0) { const parserData = JSON.parse(splitData[0]); return parserData; } return null; }; addSubscriber = async (mySession, event) => { // console.log('ADD STREAM subscribers', subscribers); const { isRoom, lstFriend, kidInfo } = this.props; if (event && event.stream) { const info = this.splitData(event.stream.connection.data); if (info && (info.role === 'TEACHER' || info.role === 'STUDENT')) { if (info.userId === kidInfo.id && info.role === 'STUDENT') { return; } if (isRoom) { const isFriend = lstFriend.find( (student) => student.student_id === info.userId, ); event.stream.isFriend = !!isFriend; } const subscriber = await mySession.subscribeAsync( event.stream, undefined, ); const subscribers = Array.from(this.state.subscribers); const streamExisted = subscribers.find( (item) => this.splitData(item.stream.connection.data).userId === info.userId, ); if (subscribers.length === 0 || !streamExisted) { subscribers.push(subscriber); } if (streamExisted) { const index = subscribers.indexOf( streamExisted.stream.streamManager, 0, ); if (index > -1) { subscribers[index] = subscriber; } } this.setState({ subscribers }); } } }; deleteSubscriber(stream) { const subscribers = Array.from(this.state.subscribers); const index = subscribers.indexOf(stream.streamManager, 0); if (index > -1) { subscribers.splice(index, 1); this.setState({ subscribers, }); } } eventReconnected = () => { const mySession = this.state.session; if (mySession) { mySession.disconnect(); const timeout = setTimeout(() => { clearTimeout(timeout); this.actionReconnected(); }, 10000); mySession.once('sessionDisconnected', (event) => { if (event.reason === 'disconnect') { clearTimeout(timeout); this.actionReconnected(); } }); } else { this.actionReconnected(); } }; actionReconnected = () => { const { reconnected } = this.props; this.clearData(); if (reconnected) { reconnected(); } }; leaveRoom() { const mySession = this.state.session; if (mySession) { mySession.disconnect(); } this.clearData(); } clearData = () => { this.OV = null; this.setState({ session: undefined, subscribers: [], myUserName: this.props.kidInfo.fullnameStudent, mainStreamManager: undefined, publisher: undefined, }); }; OnOffAudioVideo = (audio, video) => { const { mainStreamManager } = this.state; if (mainStreamManager) { mainStreamManager.publishAudio(!audio); mainStreamManager.publishVideo(!video); this.setState({ audio, video }); } }; ChangeMuteAll = (audio) => { const { mainStreamManager } = this.state; if (mainStreamManager) { mainStreamManager.publishAudio(!audio); this.setState({ audio }); } }; muteUnmuteMic = () => { const { mainStreamManager } = this.state; if (mainStreamManager) { mainStreamManager.publishAudio(!this.state.audio); this.setState({ audio: !this.state.audio }); } }; muteUnmuteCamera = () => { const { mainStreamManager } = this.state; if (mainStreamManager) { mainStreamManager.publishVideo(!this.state.video); this.setState({ video: !this.state.video }); } }; renderItem = (item, index) => { return ( <ItemConference key={index} item={item} index={index} kidInfo={this.props.kidInfo} isRoom={this.props.isRoom || false} isFullScreen={this.props.isFullScreen} subscribers={this.state.subscribers} /> ); }; render() { const { subscribers, mainStreamManager } = this.state; const { isObserve, isFullScreen } = this.props; return ( <ScrollView contentContainerStyle={ isFullScreen ? [ { flexDirection: 'row' }, subscribers.length < 3 ? { flex: 1 } : { flexWrap: 'wrap' }, ] : {} }> {mainStreamManager && !isObserve && this.renderItem(mainStreamManager, 0)} {subscribers.map((item, index) => { if (item) { return this.renderItem(item, index + 1); } })} </ScrollView> ); } }