opentok-react-native
Version:
React Native components for OpenTok iOS and Android SDKs
135 lines (130 loc) • 4.46 kB
JavaScript
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, Platform } from 'react-native';
import { createPublisher, checkAndroidPermissions, OT, removeNativeEvents, nativeEvents, setNativeEvents } from './OT';
import { sanitizeProperties, sanitizePublisherEvents } from './helpers/OTPublisherHelper';
import { handleError } from './OTError';
import OTPublisherView from './views/OTPublisherView';
import { isNull } from 'underscore';
import { isConnected } from './helpers/OTSessionHelper';
const uuid = require('uuid/v4');
class OTPublisher extends Component {
constructor(props) {
super(props);
this.state = {
initError: null,
publisher: null,
publisherId: uuid(),
};
this.componentEvents = {
sessionConnected: Platform.OS === 'android' ? 'session:onConnected' : 'session:sessionDidConnect',
};
this.componentEventsArray = Object.values(this.componentEvents);
}
componentWillMount() {
const publisherEvents = sanitizePublisherEvents(this.state.publisherId, this.props.eventHandlers);
setNativeEvents(publisherEvents);
OT.setJSComponentEvents(this.componentEventsArray);
this.sessionConnected = nativeEvents.addListener(this.componentEvents.sessionConnected, () => this.sessionConnectedHandler());
}
componentDidMount() {
this.createPublisher();
}
componentDidUpdate(previousProps) {
const useDefault = (value, defaultValue) => (value === undefined ? defaultValue : value);
const shouldUpdate = (key, defaultValue) => {
const previous = useDefault(previousProps.properties[key], defaultValue);
const current = useDefault(this.props.properties[key], defaultValue);
return previous !== current;
};
const updatePublisherProperty = (key, defaultValue) => {
if (shouldUpdate(key, defaultValue)) {
const value = useDefault(this.props.properties[key], defaultValue);
if (key === 'cameraPosition') {
OT.changeCameraPosition(this.state.publisherId, value);
} else {
OT[key](this.state.publisherId, value);
}
}
};
updatePublisherProperty('publishAudio', true);
updatePublisherProperty('publishVideo', true);
updatePublisherProperty('cameraPosition', 'front');
}
componentWillUnmount() {
OT.destroyPublisher(this.state.publisherId, (error) => {
if (error) {
handleError(error);
} else {
this.sessionConnected.remove();
OT.removeJSComponentEvents(this.componentEventsArray);
const events = sanitizePublisherEvents(this.state.publisherId, this.props.eventHandlers);
removeNativeEvents(events);
}
});
}
sessionConnectedHandler = () => {
if (isNull(this.state.publisher) && isNull(this.state.initError)) {
this.publish();
}
}
createPublisher() {
if (Platform.OS === 'android') {
checkAndroidPermissions()
.then(() => {
this.initPublisher();
})
.catch((error) => {
handleError(error);
});
} else {
this.initPublisher();
}
}
initPublisher() {
const publisherProperties = sanitizeProperties(this.props.properties);
OT.initPublisher(this.state.publisherId, publisherProperties, (initError) => {
if (initError) {
this.setState({
initError
});
handleError(initError);
} else {
OT.getSessionInfo((session) => {
if (!isNull(session) && isNull(this.state.publisher) && isConnected(session.connectionStatus)) {
this.publish();
}
});
}
});
}
publish() {
OT.publish(this.state.publisherId, (publishError) => {
if (publishError) {
handleError(publishError);
} else {
this.setState({
publisher: true,
});
}
});
}
render() {
const { publisher, publisherId } = this.state;
if (publisher && publisherId) {
return <OTPublisherView publisherId={publisherId} {...this.props} />;
}
return <View />;
}
}
const viewPropTypes = View.propTypes;
OTPublisher.propTypes = {
...viewPropTypes,
properties: PropTypes.object, // eslint-disable-line react/forbid-prop-types
eventHandlers: PropTypes.object, // eslint-disable-line react/forbid-prop-types
};
OTPublisher.defaultProps = {
properties: {},
eventHandlers: {},
};
export default OTPublisher;