2018-06-26 22:56:22 +00:00
|
|
|
// @flow
|
|
|
|
|
|
|
|
import React, { Component } from 'react';
|
|
|
|
|
2019-06-26 14:08:23 +00:00
|
|
|
import { Avatar } from '../../../base/avatar';
|
2018-06-26 22:56:22 +00:00
|
|
|
import { MEDIA_TYPE } from '../../../base/media';
|
|
|
|
import {
|
|
|
|
getParticipantDisplayName,
|
2021-07-09 12:36:19 +00:00
|
|
|
getParticipantPresenceStatus,
|
|
|
|
getRemoteParticipants
|
2018-06-26 22:56:22 +00:00
|
|
|
} from '../../../base/participants';
|
|
|
|
import { Container, Text } from '../../../base/react';
|
2019-03-21 16:38:29 +00:00
|
|
|
import { connect } from '../../../base/redux';
|
2018-06-26 22:56:22 +00:00
|
|
|
import { isLocalTrackMuted } from '../../../base/tracks';
|
|
|
|
import { CALLING, PresenceLabel } from '../../../presence-status';
|
|
|
|
|
|
|
|
import styles from './styles';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The type of the React {@code Component} props of {@link CalleeInfo}.
|
|
|
|
*/
|
|
|
|
type Props = {
|
|
|
|
|
|
|
|
/**
|
2019-06-26 14:08:23 +00:00
|
|
|
* The callee's information such as display name.
|
2018-06-26 22:56:22 +00:00
|
|
|
*/
|
|
|
|
_callee: Object,
|
|
|
|
|
|
|
|
_isVideoMuted: boolean
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements a React {@link Component} which depicts the establishment of a
|
|
|
|
* call with a specific remote callee.
|
|
|
|
*
|
2021-11-04 21:10:43 +00:00
|
|
|
* @augments Component
|
2018-06-26 22:56:22 +00:00
|
|
|
*/
|
|
|
|
class CalleeInfo extends Component<Props> {
|
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render() {
|
|
|
|
const {
|
2019-06-26 14:08:23 +00:00
|
|
|
id,
|
2018-06-26 22:56:22 +00:00
|
|
|
name,
|
|
|
|
status = CALLING
|
|
|
|
} = this.props._callee;
|
|
|
|
const className = this.props._isVideoMuted ? 'solidBG' : undefined;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Container
|
|
|
|
{ ...this._style('ringing', className) }
|
|
|
|
id = 'ringOverlay'>
|
|
|
|
<Container
|
|
|
|
{ ...this._style('ringing__content') }>
|
|
|
|
<Avatar
|
|
|
|
{ ...this._style('ringing__avatar') }
|
2019-06-26 14:08:23 +00:00
|
|
|
participantId = { id } />
|
2018-06-26 22:56:22 +00:00
|
|
|
<Container { ...this._style('ringing__status') }>
|
|
|
|
<PresenceLabel
|
|
|
|
defaultPresence = { status }
|
2018-07-09 22:18:09 +00:00
|
|
|
{ ...this._style('ringing__text') } />
|
2018-06-26 22:56:22 +00:00
|
|
|
</Container>
|
|
|
|
<Container { ...this._style('ringing__name') }>
|
|
|
|
<Text
|
|
|
|
{ ...this._style('ringing__text') }>
|
|
|
|
{ name }
|
|
|
|
</Text>
|
|
|
|
</Container>
|
|
|
|
</Container>
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to convert specified CSS class names into React
|
|
|
|
* {@link Component} props {@code style} or {@code className}.
|
|
|
|
*
|
|
|
|
* @param {Array<string>} classNames - The CSS class names to convert
|
|
|
|
* into React {@code Component} props {@code style} or {@code className}.
|
|
|
|
* @returns {{
|
|
|
|
* className: string,
|
|
|
|
* style: Object
|
|
|
|
* }}
|
|
|
|
*/
|
|
|
|
_style(...classNames: Array<?string>) {
|
|
|
|
let className = '';
|
|
|
|
let style;
|
|
|
|
|
|
|
|
for (const aClassName of classNames) {
|
|
|
|
if (aClassName) {
|
2021-03-16 15:59:33 +00:00
|
|
|
// Attempt to convert aClassName into style.
|
2018-06-26 22:56:22 +00:00
|
|
|
if (styles && aClassName in styles) {
|
|
|
|
// React Native will accept an Array as the value of the
|
|
|
|
// style prop. However, I do not know about React.
|
|
|
|
style = {
|
|
|
|
...style,
|
|
|
|
...styles[aClassName]
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
// Otherwise, leave it as className.
|
|
|
|
className += `${aClassName} `;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Choose which of the className and/or style props has a value and,
|
|
|
|
// consequently, must be returned.
|
|
|
|
const props = {};
|
|
|
|
|
|
|
|
if (className) {
|
|
|
|
props.className = className.trim();
|
|
|
|
}
|
|
|
|
if (style) {
|
|
|
|
props.style = style;
|
|
|
|
}
|
|
|
|
|
|
|
|
return props;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps (parts of) the redux state to {@code CalleeInfo}'s props.
|
|
|
|
*
|
|
|
|
* @param {Object} state - The redux state.
|
|
|
|
* @private
|
|
|
|
* @returns {{
|
|
|
|
* _callee: Object
|
|
|
|
* }}
|
|
|
|
*/
|
|
|
|
function _mapStateToProps(state) {
|
|
|
|
const _isVideoMuted
|
|
|
|
= isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.VIDEO);
|
2021-07-09 12:36:19 +00:00
|
|
|
|
|
|
|
// This would be expensive for big calls but the component will be mounted only when there are up
|
|
|
|
// to 3 participants in the call.
|
|
|
|
for (const [ id, p ] of getRemoteParticipants(state)) {
|
|
|
|
if (p.botType === 'poltergeist') {
|
|
|
|
return {
|
|
|
|
_callee: {
|
|
|
|
id,
|
|
|
|
name: getParticipantDisplayName(state, id),
|
|
|
|
status: getParticipantPresenceStatus(state, id)
|
|
|
|
},
|
|
|
|
_isVideoMuted
|
|
|
|
};
|
|
|
|
}
|
2018-06-26 22:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
_callee: state['features/invite'].initialCalleeInfo,
|
|
|
|
_isVideoMuted
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export default connect(_mapStateToProps)(CalleeInfo);
|