|
|
|
@ -1,11 +1,12 @@ |
|
|
|
|
import React, { Component } from 'react'; |
|
|
|
|
import { WithTranslation } from 'react-i18next'; |
|
|
|
|
/* eslint-disable react/jsx-no-bind */ |
|
|
|
|
import React, { useRef, useState } from 'react'; |
|
|
|
|
import { useTranslation } from 'react-i18next'; |
|
|
|
|
import { connect } from 'react-redux'; |
|
|
|
|
import { makeStyles } from 'tss-react/mui'; |
|
|
|
|
|
|
|
|
|
import { IReduxState } from '../../../app/types'; |
|
|
|
|
import Avatar from '../../../base/avatar/components/Avatar'; |
|
|
|
|
import { isNameReadOnly } from '../../../base/config/functions.web'; |
|
|
|
|
import { translate } from '../../../base/i18n/functions'; |
|
|
|
|
import { IconArrowDown, IconArrowUp, IconPhoneRinging, IconVolumeOff } from '../../../base/icons/svg'; |
|
|
|
|
import { isVideoMutedByUser } from '../../../base/media/functions'; |
|
|
|
|
import { getLocalParticipant } from '../../../base/participants/functions'; |
|
|
|
@ -14,6 +15,7 @@ import ActionButton from '../../../base/premeeting/components/web/ActionButton'; |
|
|
|
|
import PreMeetingScreen from '../../../base/premeeting/components/web/PreMeetingScreen'; |
|
|
|
|
import { updateSettings } from '../../../base/settings/actions'; |
|
|
|
|
import { getDisplayName } from '../../../base/settings/functions.web'; |
|
|
|
|
import { withPixelLineHeight } from '../../../base/styles/functions.web'; |
|
|
|
|
import { getLocalJitsiVideoTrack } from '../../../base/tracks/functions.web'; |
|
|
|
|
import Button from '../../../base/ui/components/web/Button'; |
|
|
|
|
import Input from '../../../base/ui/components/web/Input'; |
|
|
|
@ -33,7 +35,7 @@ import { |
|
|
|
|
|
|
|
|
|
import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog'; |
|
|
|
|
|
|
|
|
|
interface IProps extends WithTranslation { |
|
|
|
|
interface IProps { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Indicates whether the display name is editable. |
|
|
|
@ -116,45 +118,90 @@ interface IProps extends WithTranslation { |
|
|
|
|
videoTrack?: Object; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
interface IState { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Flag controlling the visibility of the 'join by phone' buttons. |
|
|
|
|
*/ |
|
|
|
|
showJoinByPhoneButtons: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This component is displayed before joining a meeting. |
|
|
|
|
*/ |
|
|
|
|
class Prejoin extends Component<IProps, IState> { |
|
|
|
|
showDisplayNameField: boolean; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Initializes a new {@code Prejoin} instance. |
|
|
|
|
* |
|
|
|
|
* @inheritdoc |
|
|
|
|
*/ |
|
|
|
|
constructor(props: IProps) { |
|
|
|
|
super(props); |
|
|
|
|
|
|
|
|
|
this.state = { |
|
|
|
|
showJoinByPhoneButtons: false |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this._closeDialog = this._closeDialog.bind(this); |
|
|
|
|
this._showDialog = this._showDialog.bind(this); |
|
|
|
|
this._onJoinButtonClick = this._onJoinButtonClick.bind(this); |
|
|
|
|
this._onDropdownClose = this._onDropdownClose.bind(this); |
|
|
|
|
this._onOptionsClick = this._onOptionsClick.bind(this); |
|
|
|
|
this._setName = this._setName.bind(this); |
|
|
|
|
this._onJoinConferenceWithoutAudioKeyPress = this._onJoinConferenceWithoutAudioKeyPress.bind(this); |
|
|
|
|
this._showDialogKeyPress = this._showDialogKeyPress.bind(this); |
|
|
|
|
this._getExtraJoinButtons = this._getExtraJoinButtons.bind(this); |
|
|
|
|
this._onInputKeyPress = this._onInputKeyPress.bind(this); |
|
|
|
|
|
|
|
|
|
this.showDisplayNameField = props.canEditDisplayName || props.showErrorOnJoin; |
|
|
|
|
} |
|
|
|
|
const useStyles = makeStyles()(theme => { |
|
|
|
|
return { |
|
|
|
|
inputContainer: { |
|
|
|
|
width: '100%' |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
input: { |
|
|
|
|
width: '100%', |
|
|
|
|
marginBottom: theme.spacing(3), |
|
|
|
|
|
|
|
|
|
'& input': { |
|
|
|
|
textAlign: 'center' |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
avatarContainer: { |
|
|
|
|
display: 'flex', |
|
|
|
|
alignItems: 'center', |
|
|
|
|
flexDirection: 'column' |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
avatar: { |
|
|
|
|
margin: `${theme.spacing(2)} auto ${theme.spacing(3)}` |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
avatarName: { |
|
|
|
|
...withPixelLineHeight(theme.typography.bodyShortBoldLarge), |
|
|
|
|
color: theme.palette.text01, |
|
|
|
|
marginBottom: theme.spacing(5), |
|
|
|
|
textAlign: 'center' |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
error: { |
|
|
|
|
backgroundColor: theme.palette.actionDanger, |
|
|
|
|
color: theme.palette.text01, |
|
|
|
|
borderRadius: theme.shape.borderRadius, |
|
|
|
|
width: '100%', |
|
|
|
|
...withPixelLineHeight(theme.typography.labelRegular), |
|
|
|
|
boxSizing: 'border-box', |
|
|
|
|
padding: theme.spacing(1), |
|
|
|
|
textAlign: 'center', |
|
|
|
|
marginTop: `-${theme.spacing(2)}`, |
|
|
|
|
marginBottom: theme.spacing(3) |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
dropdownContainer: { |
|
|
|
|
position: 'relative', |
|
|
|
|
width: '100%' |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
dropdownButtons: { |
|
|
|
|
width: '300px', |
|
|
|
|
padding: '8px 0', |
|
|
|
|
backgroundColor: theme.palette.action02, |
|
|
|
|
color: theme.palette.text04, |
|
|
|
|
borderRadius: theme.shape.borderRadius, |
|
|
|
|
position: 'relative', |
|
|
|
|
top: `-${theme.spacing(3)}` |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const Prejoin = ({ |
|
|
|
|
canEditDisplayName, |
|
|
|
|
deviceStatusVisible, |
|
|
|
|
hasJoinByPhoneButton, |
|
|
|
|
joinConference, |
|
|
|
|
joinConferenceWithoutAudio, |
|
|
|
|
joiningInProgress, |
|
|
|
|
name, |
|
|
|
|
participantId, |
|
|
|
|
prejoinConfig, |
|
|
|
|
readOnlyName, |
|
|
|
|
setJoinByPhoneDialogVisiblity, |
|
|
|
|
showCameraPreview, |
|
|
|
|
showDialog, |
|
|
|
|
showErrorOnJoin, |
|
|
|
|
updateSettings: dispatchUpdateSettings, |
|
|
|
|
videoTrack |
|
|
|
|
}: IProps) => { |
|
|
|
|
const showDisplayNameField = useRef(canEditDisplayName || showErrorOnJoin); |
|
|
|
|
const [ showJoinByPhoneButtons, setShowJoinByPhoneButtons ] = useState(false); |
|
|
|
|
const { classes } = useStyles(); |
|
|
|
|
const { t } = useTranslation(); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Handler for the join button. |
|
|
|
@ -162,23 +209,21 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* @param {Object} e - The synthetic event. |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_onJoinButtonClick() { |
|
|
|
|
if (this.props.showErrorOnJoin) { |
|
|
|
|
const onJoinButtonClick = () => { |
|
|
|
|
if (showErrorOnJoin) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
this.props.joinConference(); |
|
|
|
|
} |
|
|
|
|
joinConference(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Closes the dropdown. |
|
|
|
|
* |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_onDropdownClose() { |
|
|
|
|
this.setState({ |
|
|
|
|
showJoinByPhoneButtons: false |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
const onDropdownClose = () => { |
|
|
|
|
setShowJoinByPhoneButtons(false); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Displays the join by phone buttons dropdown. |
|
|
|
@ -186,13 +231,11 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* @param {Object} e - The synthetic event. |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_onOptionsClick(e?: React.KeyboardEvent | React.MouseEvent | undefined) { |
|
|
|
|
const onOptionsClick = (e?: React.KeyboardEvent | React.MouseEvent | undefined) => { |
|
|
|
|
e?.stopPropagation(); |
|
|
|
|
|
|
|
|
|
this.setState({ |
|
|
|
|
showJoinByPhoneButtons: !this.state.showJoinByPhoneButtons |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
setShowJoinByPhoneButtons(show => !show); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the guest participant name. |
|
|
|
@ -200,30 +243,30 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* @param {string} displayName - Participant name. |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_setName(displayName: string) { |
|
|
|
|
this.props.updateSettings({ |
|
|
|
|
const setName = (displayName: string) => { |
|
|
|
|
dispatchUpdateSettings({ |
|
|
|
|
displayName |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Closes the join by phone dialog. |
|
|
|
|
* |
|
|
|
|
* @returns {undefined} |
|
|
|
|
*/ |
|
|
|
|
_closeDialog() { |
|
|
|
|
this.props.setJoinByPhoneDialogVisiblity(false); |
|
|
|
|
} |
|
|
|
|
const closeDialog = () => { |
|
|
|
|
setJoinByPhoneDialogVisiblity(false); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Displays the dialog for joining a meeting by phone. |
|
|
|
|
* |
|
|
|
|
* @returns {undefined} |
|
|
|
|
*/ |
|
|
|
|
_showDialog() { |
|
|
|
|
this.props.setJoinByPhoneDialogVisiblity(true); |
|
|
|
|
this._onDropdownClose(); |
|
|
|
|
} |
|
|
|
|
const doShowDialog = () => { |
|
|
|
|
setJoinByPhoneDialogVisiblity(true); |
|
|
|
|
onDropdownClose(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* KeyPress handler for accessibility. |
|
|
|
@ -232,12 +275,12 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_showDialogKeyPress(e: React.KeyboardEvent) { |
|
|
|
|
const showDialogKeyPress = (e: React.KeyboardEvent) => { |
|
|
|
|
if (e.key === ' ' || e.key === 'Enter') { |
|
|
|
|
e.preventDefault(); |
|
|
|
|
this._showDialog(); |
|
|
|
|
doShowDialog(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* KeyPress handler for accessibility. |
|
|
|
@ -246,30 +289,28 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_onJoinConferenceWithoutAudioKeyPress(e: React.KeyboardEvent) { |
|
|
|
|
if (this.props.joinConferenceWithoutAudio |
|
|
|
|
const onJoinConferenceWithoutAudioKeyPress = (e: React.KeyboardEvent) => { |
|
|
|
|
if (joinConferenceWithoutAudio |
|
|
|
|
&& (e.key === ' ' |
|
|
|
|
|| e.key === 'Enter')) { |
|
|
|
|
e.preventDefault(); |
|
|
|
|
this.props.joinConferenceWithoutAudio(); |
|
|
|
|
joinConferenceWithoutAudio(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets the list of extra join buttons. |
|
|
|
|
* |
|
|
|
|
* @returns {Object} - The list of extra buttons. |
|
|
|
|
*/ |
|
|
|
|
_getExtraJoinButtons() { |
|
|
|
|
const { joinConferenceWithoutAudio, t } = this.props; |
|
|
|
|
|
|
|
|
|
const getExtraJoinButtons = () => { |
|
|
|
|
const noAudio = { |
|
|
|
|
key: 'no-audio', |
|
|
|
|
testId: 'prejoin.joinWithoutAudio', |
|
|
|
|
icon: IconVolumeOff, |
|
|
|
|
label: t('prejoin.joinWithoutAudio'), |
|
|
|
|
onClick: joinConferenceWithoutAudio, |
|
|
|
|
onKeyPress: this._onJoinConferenceWithoutAudioKeyPress |
|
|
|
|
onKeyPress: onJoinConferenceWithoutAudioKeyPress |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const byPhone = { |
|
|
|
@ -277,15 +318,15 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
testId: 'prejoin.joinByPhone', |
|
|
|
|
icon: IconPhoneRinging, |
|
|
|
|
label: t('prejoin.joinAudioByPhone'), |
|
|
|
|
onClick: this._showDialog, |
|
|
|
|
onKeyPress: this._showDialogKeyPress |
|
|
|
|
onClick: doShowDialog, |
|
|
|
|
onKeyPress: showDialogKeyPress |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
noAudio, |
|
|
|
|
byPhone |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Handle keypress on input. |
|
|
|
@ -293,127 +334,99 @@ class Prejoin extends Component<IProps, IState> { |
|
|
|
|
* @param {KeyboardEvent} e - Keyboard event. |
|
|
|
|
* @returns {void} |
|
|
|
|
*/ |
|
|
|
|
_onInputKeyPress(e: React.KeyboardEvent) { |
|
|
|
|
const { joinConference } = this.props; |
|
|
|
|
|
|
|
|
|
const onInputKeyPress = (e: React.KeyboardEvent) => { |
|
|
|
|
if (e.key === 'Enter') { |
|
|
|
|
joinConference(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Implements React's {@link Component#render()}. |
|
|
|
|
* |
|
|
|
|
* @inheritdoc |
|
|
|
|
* @returns {ReactElement} |
|
|
|
|
*/ |
|
|
|
|
render() { |
|
|
|
|
const { |
|
|
|
|
deviceStatusVisible, |
|
|
|
|
hasJoinByPhoneButton, |
|
|
|
|
joinConferenceWithoutAudio, |
|
|
|
|
joiningInProgress, |
|
|
|
|
name, |
|
|
|
|
participantId, |
|
|
|
|
prejoinConfig, |
|
|
|
|
readOnlyName, |
|
|
|
|
showCameraPreview, |
|
|
|
|
showDialog, |
|
|
|
|
showErrorOnJoin, |
|
|
|
|
t, |
|
|
|
|
videoTrack |
|
|
|
|
} = this.props; |
|
|
|
|
const { _closeDialog, _onDropdownClose, _onJoinButtonClick, |
|
|
|
|
_onOptionsClick, _setName, _onInputKeyPress } = this; |
|
|
|
|
|
|
|
|
|
const extraJoinButtons = this._getExtraJoinButtons(); |
|
|
|
|
let extraButtonsToRender = Object.values(extraJoinButtons).filter((val: any) => |
|
|
|
|
!(prejoinConfig?.hideExtraJoinButtons || []).includes(val.key) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if (!hasJoinByPhoneButton) { |
|
|
|
|
extraButtonsToRender = extraButtonsToRender.filter((btn: any) => btn.key !== 'by-phone'); |
|
|
|
|
} |
|
|
|
|
const hasExtraJoinButtons = Boolean(extraButtonsToRender.length); |
|
|
|
|
const { showJoinByPhoneButtons } = this.state; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<PreMeetingScreen |
|
|
|
|
showDeviceStatus = { deviceStatusVisible } |
|
|
|
|
title = { t('prejoin.joinMeeting') } |
|
|
|
|
videoMuted = { !showCameraPreview } |
|
|
|
|
videoTrack = { videoTrack }> |
|
|
|
|
<div |
|
|
|
|
className = 'prejoin-input-area' |
|
|
|
|
data-testid = 'prejoin.screen'> |
|
|
|
|
{this.showDisplayNameField ? (<Input |
|
|
|
|
autoComplete = { 'name' } |
|
|
|
|
autoFocus = { true } |
|
|
|
|
className = 'prejoin-input' |
|
|
|
|
error = { showErrorOnJoin } |
|
|
|
|
onChange = { _setName } |
|
|
|
|
onKeyPress = { _onInputKeyPress } |
|
|
|
|
placeholder = { t('dialog.enterDisplayName') } |
|
|
|
|
readOnly = { readOnlyName } |
|
|
|
|
value = { name } /> |
|
|
|
|
) : ( |
|
|
|
|
<div className = 'prejoin-avatar-container'> |
|
|
|
|
<Avatar |
|
|
|
|
className = 'prejoin-avatar' |
|
|
|
|
displayName = { name } |
|
|
|
|
participantId = { participantId } |
|
|
|
|
size = { 72 } /> |
|
|
|
|
<div className = 'prejoin-avatar-name'>{name}</div> |
|
|
|
|
</div> |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
{showErrorOnJoin && <div |
|
|
|
|
className = 'prejoin-error' |
|
|
|
|
data-testid = 'prejoin.errorMessage'>{t('prejoin.errorMissingName')}</div>} |
|
|
|
|
|
|
|
|
|
<div className = 'prejoin-preview-dropdown-container'> |
|
|
|
|
<Popover |
|
|
|
|
content = { hasExtraJoinButtons && <div className = 'prejoin-preview-dropdown-btns'> |
|
|
|
|
{extraButtonsToRender.map(({ key, ...rest }) => ( |
|
|
|
|
<Button |
|
|
|
|
disabled = { joiningInProgress } |
|
|
|
|
fullWidth = { true } |
|
|
|
|
key = { key } |
|
|
|
|
type = { BUTTON_TYPES.SECONDARY } |
|
|
|
|
{ ...rest } /> |
|
|
|
|
))} |
|
|
|
|
</div> } |
|
|
|
|
onPopoverClose = { _onDropdownClose } |
|
|
|
|
position = 'bottom' |
|
|
|
|
trigger = 'click' |
|
|
|
|
visible = { showJoinByPhoneButtons }> |
|
|
|
|
<ActionButton |
|
|
|
|
OptionsIcon = { showJoinByPhoneButtons ? IconArrowUp : IconArrowDown } |
|
|
|
|
ariaDropDownLabel = { t('prejoin.joinWithoutAudio') } |
|
|
|
|
ariaLabel = { t('prejoin.joinMeeting') } |
|
|
|
|
ariaPressed = { showJoinByPhoneButtons } |
|
|
|
|
disabled = { joiningInProgress } |
|
|
|
|
hasOptions = { hasExtraJoinButtons } |
|
|
|
|
onClick = { _onJoinButtonClick } |
|
|
|
|
onOptionsClick = { _onOptionsClick } |
|
|
|
|
role = 'button' |
|
|
|
|
tabIndex = { 0 } |
|
|
|
|
testId = 'prejoin.joinMeeting' |
|
|
|
|
type = 'primary'> |
|
|
|
|
{ t('prejoin.joinMeeting') } |
|
|
|
|
</ActionButton> |
|
|
|
|
</Popover> |
|
|
|
|
const extraJoinButtons = getExtraJoinButtons(); |
|
|
|
|
let extraButtonsToRender = Object.values(extraJoinButtons).filter((val: any) => |
|
|
|
|
!(prejoinConfig?.hideExtraJoinButtons || []).includes(val.key) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if (!hasJoinByPhoneButton) { |
|
|
|
|
extraButtonsToRender = extraButtonsToRender.filter((btn: any) => btn.key !== 'by-phone'); |
|
|
|
|
} |
|
|
|
|
const hasExtraJoinButtons = Boolean(extraButtonsToRender.length); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<PreMeetingScreen |
|
|
|
|
showDeviceStatus = { deviceStatusVisible } |
|
|
|
|
title = { t('prejoin.joinMeeting') } |
|
|
|
|
videoMuted = { !showCameraPreview } |
|
|
|
|
videoTrack = { videoTrack }> |
|
|
|
|
<div |
|
|
|
|
className = { classes.inputContainer } |
|
|
|
|
data-testid = 'prejoin.screen'> |
|
|
|
|
{showDisplayNameField.current ? (<Input |
|
|
|
|
autoComplete = { 'name' } |
|
|
|
|
autoFocus = { true } |
|
|
|
|
className = { classes.input } |
|
|
|
|
error = { showErrorOnJoin } |
|
|
|
|
onChange = { setName } |
|
|
|
|
onKeyPress = { onInputKeyPress } |
|
|
|
|
placeholder = { t('dialog.enterDisplayName') } |
|
|
|
|
readOnly = { readOnlyName } |
|
|
|
|
value = { name } /> |
|
|
|
|
) : ( |
|
|
|
|
<div className = { classes.avatarContainer }> |
|
|
|
|
<Avatar |
|
|
|
|
className = { classes.avatar } |
|
|
|
|
displayName = { name } |
|
|
|
|
participantId = { participantId } |
|
|
|
|
size = { 72 } /> |
|
|
|
|
<div className = { classes.avatarName }>{name}</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{ showDialog && ( |
|
|
|
|
<JoinByPhoneDialog // @ts-ignore |
|
|
|
|
joinConferenceWithoutAudio = { joinConferenceWithoutAudio } |
|
|
|
|
onClose = { _closeDialog } /> |
|
|
|
|
)} |
|
|
|
|
</PreMeetingScreen> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{showErrorOnJoin && <div |
|
|
|
|
className = { classes.error } |
|
|
|
|
data-testid = 'prejoin.errorMessage'>{t('prejoin.errorMissingName')}</div>} |
|
|
|
|
|
|
|
|
|
<div className = { classes.dropdownContainer }> |
|
|
|
|
<Popover |
|
|
|
|
content = { hasExtraJoinButtons && <div className = { classes.dropdownButtons }> |
|
|
|
|
{extraButtonsToRender.map(({ key, ...rest }) => ( |
|
|
|
|
<Button |
|
|
|
|
disabled = { joiningInProgress } |
|
|
|
|
fullWidth = { true } |
|
|
|
|
key = { key } |
|
|
|
|
type = { BUTTON_TYPES.SECONDARY } |
|
|
|
|
{ ...rest } /> |
|
|
|
|
))} |
|
|
|
|
</div> } |
|
|
|
|
onPopoverClose = { onDropdownClose } |
|
|
|
|
position = 'bottom' |
|
|
|
|
trigger = 'click' |
|
|
|
|
visible = { showJoinByPhoneButtons }> |
|
|
|
|
<ActionButton |
|
|
|
|
OptionsIcon = { showJoinByPhoneButtons ? IconArrowUp : IconArrowDown } |
|
|
|
|
ariaDropDownLabel = { t('prejoin.joinWithoutAudio') } |
|
|
|
|
ariaLabel = { t('prejoin.joinMeeting') } |
|
|
|
|
ariaPressed = { showJoinByPhoneButtons } |
|
|
|
|
disabled = { joiningInProgress } |
|
|
|
|
hasOptions = { hasExtraJoinButtons } |
|
|
|
|
onClick = { onJoinButtonClick } |
|
|
|
|
onOptionsClick = { onOptionsClick } |
|
|
|
|
role = 'button' |
|
|
|
|
tabIndex = { 0 } |
|
|
|
|
testId = 'prejoin.joinMeeting' |
|
|
|
|
type = 'primary'> |
|
|
|
|
{t('prejoin.joinMeeting')} |
|
|
|
|
</ActionButton> |
|
|
|
|
</Popover> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{showDialog && ( |
|
|
|
|
<JoinByPhoneDialog |
|
|
|
|
joinConferenceWithoutAudio = { joinConferenceWithoutAudio } |
|
|
|
|
onClose = { closeDialog } /> |
|
|
|
|
)} |
|
|
|
|
</PreMeetingScreen> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Maps (parts of) the redux state to the React {@code Component} props. |
|
|
|
@ -450,4 +463,4 @@ const mapDispatchToProps = { |
|
|
|
|
updateSettings |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(translate(Prejoin)); |
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(Prejoin); |
|
|
|
|