jiti-meet/react/features/invite/components/InviteButton.web.js

237 lines
6.8 KiB
JavaScript

/* global interfaceConfig */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Button from '@atlaskit/button';
import DropdownMenu from '@atlaskit/dropdown-menu';
import { translate } from '../../base/i18n';
import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
import { openDialog } from '../../base/dialog';
import { AddPeopleDialog, InviteDialog } from '.';
import { DialOutDialog } from '../../dial-out';
import { isInviteOptionEnabled, getInviteOptionPosition } from '../functions';
const SHARE_LINK_OPTION = 'invite';
const DIAL_OUT_OPTION = 'dialout';
const ADD_TO_CALL_OPTION = 'addtocall';
/**
* The button that provides different invite options.
*/
class InviteButton extends Component {
/**
* {@code InviteButton}'s property types.
*
* @static
*/
static propTypes = {
/**
* Indicates if the "Add to call" feature is available.
*/
_isAddToCallAvailable: PropTypes.bool,
/**
* Indicates if the "Dial out" feature is available.
*/
_isDialOutAvailable: PropTypes.bool,
/**
* The function opening the dialog.
*/
openDialog: PropTypes.func,
/**
* Invoked to obtain translated strings.
*/
t: PropTypes.func
};
/**
* Initializes a new {@code InviteButton} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
this._onInviteClick = this._onInviteClick.bind(this);
this._onInviteOptionSelected = this._onInviteOptionSelected.bind(this);
this._updateInviteItems = this._updateInviteItems.bind(this);
this._updateInviteItems(this.props);
}
/**
* Implements React's {@link Component#componentWillReceiveProps()}.
*
* @inheritdoc
* @param {Object} nextProps - The read-only props which this Component will
* receive.
* @returns {void}
*/
componentWillReceiveProps(nextProps) {
if (this.props._isDialOutAvailable !== nextProps._isDialOutAvailable
|| this.props._isAddToCallAvailable
!== nextProps._isAddToCallAvailable) {
this._updateInviteItems(nextProps);
}
}
/**
* Renders the content of this component.
*
* @returns {ReactElement}
*/
render() {
const { t } = this.props;
const { VERTICAL_FILMSTRIP } = interfaceConfig;
return (
<div className = 'filmstrip__invite'>
<div className = 'invite-button-group'>
<Button
onClick = { this._onInviteClick }
shouldFitContainer = { true }>
{ t('invite.invitePeople') }
</Button>
{ this.props._isDialOutAvailable
|| this.props._isAddToCallAvailable
? <DropdownMenu
items = { this.state.inviteOptions }
onItemActivated = { this._onInviteOptionSelected }
position = { VERTICAL_FILMSTRIP
? 'bottom right'
: 'top right' }
shouldFlip = { true }
triggerType = 'button' />
: null }
</div>
</div>
);
}
/**
* Handles the click of the invite button.
*
* @private
* @returns {void}
*/
_onInviteClick() {
this.props.openDialog(InviteDialog);
}
/**
* Handles selection of the invite options.
*
* @param { Object } option - The invite option that has been selected from
* the dropdown menu.
* @private
* @returns {void}
*/
_onInviteOptionSelected(option) {
this.state.inviteOptions[0].items.forEach(item => {
if (item.content === option.item.content) {
item.action();
}
});
}
/**
* Updates the invite items list depending on the availability of the
* features.
*
* @param {Object} props - The read-only properties of the component.
* @private
* @returns {void}
*/
_updateInviteItems(props) {
const { t } = this.props;
const inviteItems = [];
inviteItems.splice(
getInviteOptionPosition(SHARE_LINK_OPTION),
0,
{
content: t('toolbar.invite'),
action: () => this.props.openDialog(InviteDialog)
}
);
if (props._isDialOutAvailable) {
inviteItems.splice(
getInviteOptionPosition(DIAL_OUT_OPTION),
0,
{
content: t('dialOut.dialOut'),
action: () => this.props.openDialog(DialOutDialog)
}
);
}
if (props._isAddToCallAvailable) {
inviteItems.splice(
getInviteOptionPosition(ADD_TO_CALL_OPTION),
0,
{
content: interfaceConfig.ADD_PEOPLE_APP_NAME,
action: () => this.props.openDialog(AddPeopleDialog)
}
);
}
const nextState = {
/**
* The list of invite options.
*/
inviteOptions: [
{
items: inviteItems
}
]
};
if (this.state) {
this.setState(nextState);
} else {
// eslint-disable-next-line react/no-direct-mutation-state
this.state = nextState;
}
}
}
/**
* Maps (parts of) the Redux state to the associated {@code InviteButton}'s
* props.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _isAddToCallAvailable: boolean,
* _isDialOutAvailable: boolean
* }}
*/
function _mapStateToProps(state) {
const { conference } = state['features/base/conference'];
const { enableUserRolesBasedOnToken } = state['features/base/config'];
const { isGuest } = state['features/base/jwt'];
return {
_isAddToCallAvailable:
!isGuest && isInviteOptionEnabled(ADD_TO_CALL_OPTION),
_isDialOutAvailable:
getLocalParticipant(state).role === PARTICIPANT_ROLE.MODERATOR
&& conference && conference.isSIPCallingSupported()
&& isInviteOptionEnabled(DIAL_OUT_OPTION)
&& (!enableUserRolesBasedOnToken || !isGuest)
};
}
export default translate(connect(_mapStateToProps, { openDialog })(
InviteButton));