react-native-classroom
Version:
React Native Class room
451 lines (414 loc) • 13.1 kB
JavaScript
/* 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>
);
}
}