opentok-react-native
Version:
Vonage Video client SDK for React Native
222 lines (221 loc) • 8.22 kB
JavaScript
"use strict";
import React from 'react';
import { Platform, View } from 'react-native';
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
import PropTypes from 'prop-types';
import { isEqual } from 'underscore';
import uuid from 'react-native-uuid';
import { checkAndroidPermissions, OT } from "./OT.js";
import OTRNPublisher from './OTPublisherNativeComponent';
import { addEventListener, removeEventListener, dispatchEvent, isConnected, getPublisherStream } from "./helpers/OTSessionHelper.js";
import { sanitizeProperties } from "./helpers/OTPublisherHelper.js";
import OTContext from "./contexts/OTContext.js";
import { jsx as _jsx } from "react/jsx-runtime";
export default class OTPublisher extends React.Component {
eventHandlers = {};
publisherProperties = {};
constructor(props) {
super(props);
const mergedProperties = {
...OTPublisher.defaultProps.properties,
...props.properties
};
this.state = {
publisherId: uuid.v4(),
publishVideo: mergedProperties.publishVideo,
permissionsGranted: Platform.OS === 'ios',
componentMounted: false,
publisherProperties: sanitizeProperties(mergedProperties)
};
this.eventHandlers = props.eventHandlers;
this.initComponent(props.eventHandlers);
}
componentDidMount() {
addEventListener(this.context.sessionId, 'sessionConnected', this.onSessionConnected);
this.setState({
componentMounted: true
});
}
componentDidUpdate() {
const {
properties
} = this.props;
const sanitizedProperties = sanitizeProperties(properties);
if (!isEqual(this.state.publisherProperties, sanitizedProperties)) {
this.setState(prevState => ({
publisherProperties: sanitizedProperties
}));
}
}
onSessionConnected = () => {
if (Platform.OS === 'android') {
const {
audioTrack,
videoTrack,
videoSource
} = this.state.publisherProperties;
const isScreenSharing = videoSource === 'screen';
checkAndroidPermissions(audioTrack, videoTrack, isScreenSharing).then(() => {
OT.publish(this.context.sessionId, this.state.publisherId);
this.setState({
permissionsGranted: true
});
}).catch(error => {
// this.otrnEventHandler(error);
});
} else {
OT.publish(this.context.sessionId, this.state.publisherId);
}
};
initComponent = () => {
this.eventHandlers.streamCreated = this.props.eventHandlers?.streamCreated;
this.eventHandlers.streamDestroyed = this.props.eventHandlers?.streamDestroyed;
this.eventHandlers.error = this.props.eventHandlers?.error;
this.eventHandlers.audioLevel = this.props.eventHandlers?.audioLevel;
this.eventHandlers.audioNetworkStats = this.props.eventHandlers?.audioNetworkStats;
this.eventHandlers.rtcStatsReport = this.props.eventHandlers?.rtcStatsReport;
this.eventHandlers.videoDisabled = this.props.eventHandlers?.videoDisabled;
this.eventHandlers.videoDisableWarning = this.props.eventHandlers?.videoDisableWarning;
this.eventHandlers.videoDisableWarningLifted = this.props.eventHandlers?.videoDisableWarningLifted;
this.eventHandlers.videoEnabled = this.props.eventHandlers?.videoEnabled;
this.eventHandlers.videoNetworkStats = this.props.eventHandlers?.videoNetworkStats;
this.publisherProperties = sanitizeProperties(this.props.properties);
if (Platform.OS === 'android') {
const {
audioTrack,
videoTrack,
videoSource
} = this.publisherProperties;
const isScreenSharing = videoSource === 'screen';
checkAndroidPermissions(audioTrack, videoTrack, isScreenSharing).then(() => {
if (this.context && isConnected(this.context.sessionId)) {
setTimeout(() => OT.publish(this.context.sessionId, this.state.publisherId), 0);
}
this.setState({
permissionsGranted: true
});
}).catch(error => {
// this.otrnEventHandler(error);
});
} else {
// Context and publisherId might not be available immediately
// So we delay the publish call slightly
setTimeout(() => {
if (this.context && isConnected(this.context.sessionId)) {
OT.publish(this.context.sessionId, this.state.publisherId);
}
}, 100);
}
};
getRtcStatsReport() {
//NOSONAR - this method is exposed externally
OT.getPublisherRtcStatsReport(this.context.sessionId, this.state.publisherId);
}
componentWillUnmount() {
OT.unpublish(this.context.sessionId, this.state.publisherId);
const publisherStreamId = getPublisherStream(this.context.sessionId);
if (publisherStreamId) {
const event = {
streamId: publisherStreamId,
nativeEvent: {
streamId: publisherStreamId
}
};
this.onStreamDestroyed(event);
}
removeEventListener(this.context.sessionId, 'sessionConnected', this.onSessionConnected);
}
getPrePermissionViewStyle = () => ({
backgroundColor: '#000',
...this.props.style
});
onStreamDestroyed = event => {
dispatchEvent(this.context.sessionId, 'publisherStreamDestroyed', event);
this.props.eventHandlers?.streamDestroyed?.(event.nativeEvent);
};
render() {
return this.state.permissionsGranted && this.state.componentMounted ? /*#__PURE__*/_jsx(OTRNPublisher, {
sessionId: this.context.sessionId,
publisherId: this.state.publisherId,
onError: event => {
this.props.eventHandlers?.error?.(event.nativeEvent);
},
onStreamCreated: event => {
dispatchEvent(this.context.sessionId, 'publisherStreamCreated', event.nativeEvent);
this.props.eventHandlers?.streamCreated?.(event.nativeEvent);
},
onStreamDestroyed: this.onStreamDestroyed,
onAudioLevel: event => {
this.props.eventHandlers?.audioLevel?.(event.nativeEvent);
},
onAudioNetworkStats: event => {
// TODO - remove workaround for Android stats prop
const eventData = event.nativeEvent.jsonStats ? JSON.parse(event.nativeEvent.jsonStats) : event.nativeEvent.stats;
this.props.eventHandlers?.audioNetworkStats?.(eventData);
},
onRtcStatsReport: event => {
this.props.eventHandlers?.rtcStatsReport?.(JSON.parse(event.nativeEvent.jsonStats));
},
onVideoDisabled: event => {
this.props.eventHandlers?.videoDisabled?.(event.nativeEvent);
},
onVideoDisableWarning: event => {
this.props.eventHandlers?.videoDisableWarning?.(event.nativeEvent);
},
onVideoDisableWarningLifted: event => {
this.props.eventHandlers?.videoDisableWarningLifted?.(event.nativeEvent);
},
onVideoEnabled: event => {
this.props.eventHandlers?.videoEnabled?.(event.nativeEvent);
},
onVideoNetworkStats: event => {
// TODO - remove workaround for Android stats prop
const eventData = event.nativeEvent.jsonStats ? JSON.parse(event.nativeEvent.jsonStats) : event.nativeEvent.stats;
this.props.eventHandlers?.videoNetworkStats?.(eventData);
},
style: this.props.style,
...this.state.publisherProperties
}) : /*#__PURE__*/_jsx(View, {
style: this.getPrePermissionViewStyle()
});
}
}
OTPublisher.propTypes = {
eventHandlers: PropTypes.object,
properties: PropTypes.object,
style: ViewPropTypes.style
};
OTPublisher.defaultProps = {
eventHandlers: {},
properties: {
publishAudio: true,
publishVideo: true,
audioBitrate: 40000,
audioFallback: {
publisher: false,
subscriber: true
},
audioTrack: true,
cameraPosition: 'front',
enableDtx: false,
frameRate: 30,
name: '',
publishCaptions: false,
scalableScreenshare: false,
allowAudioCaptureWhileMuted: false,
publishSenderStats: false,
resolution: 'MEDIUM',
videoTrack: true,
videoSource: 'camera',
videoContentHint: '',
maxVideoBitrate: 0,
videoBitratePreset: 'default',
scaleBehavior: 'fill',
preferredVideoCodecs: ''
},
style: {
flex: 1
}
};
OTPublisher.contextType = OTContext;
//# sourceMappingURL=OTPublisher.js.map