feat(prejoin) Disable join buttons during joining

- use new `Button` component for drop down buttons
This commit is contained in:
Horatiu Muresan 2023-01-04 14:22:51 +02:00 committed by GitHub
parent 82fd465819
commit 0ad52a06ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 120 deletions

View File

@ -50,7 +50,7 @@
* Override default InlineDialog behaviour, since it does not play nicely with relative widths
*/
& > div:nth-child(2) {
background: #fff;
background: #E0E0E0;
padding: 0;
position: absolute !important;
width: 100%;

View File

@ -34,6 +34,11 @@ export interface IButtonProps {
*/
onClick?: (e?: React.MouseEvent<HTMLButtonElement> | GestureResponderEvent) => void;
/**
* Key press callback.
*/
onKeyPress?: (e?: React.KeyboardEvent<HTMLButtonElement>) => void;
/**
* The type of button to be displayed.
*/

View File

@ -187,6 +187,7 @@ const Button = React.forwardRef<any, any>(({
label,
labelKey,
onClick = () => null,
onKeyPress = () => null,
size = 'medium',
testId,
type = BUTTON_TYPES.PRIMARY
@ -206,6 +207,7 @@ const Button = React.forwardRef<any, any>(({
disabled = { disabled }
{ ...(id ? { id } : {}) }
onClick = { onClick }
onKeyPress = { onKeyPress }
ref = { ref }
title = { accessibilityLabel }
type = { isSubmit ? 'submit' : 'button' }>

View File

@ -1,95 +0,0 @@
import React from 'react';
import { makeStyles } from 'tss-react/mui';
import Icon from '../../../base/icons/components/Icon';
interface IProps {
/**
* Attribute used in automated testing.
*/
dataTestId: string;
/**
* The button's icon.
*/
icon: Function;
/**
* The button's label.
*/
label: string;
/**
* Function to be called when button is clicked.
*/
onButtonClick: (e?: React.MouseEvent) => void;
/**
* Function to be called on key pressed.
*/
onKeyPressed: (e?: React.KeyboardEvent) => void;
}
const useStyles = makeStyles()(theme => {
return {
prejoinPreviewDropdownBtn: {
alignItems: 'center',
color: '#1C2025',
cursor: 'pointer',
display: 'flex',
height: 40,
fontSize: 15,
lineHeight: '24px',
padding: '0 16px', // @ts-ignore
backgroundColor: theme.palette.field02,
'&:hover': { // @ts-ignore
backgroundColor: theme.palette.field02Hover
}
},
prejoinPreviewDropdownIcon: {
display: 'inline-block',
marginRight: 16,
'& > svg': {
fill: '#1C2025'
}
}
};
});
/**
* Buttons used for pre meeting actions.
*
* @returns {ReactElement}
*/
const DropdownButton = ({
dataTestId,
icon,
onButtonClick,
onKeyPressed,
label
}: IProps) => {
const { classes } = useStyles();
return (
<div
className = { classes.prejoinPreviewDropdownBtn }
data-testid = { dataTestId }
onClick = { onButtonClick }
onKeyPress = { onKeyPressed }
role = 'button'
tabIndex = { 0 }>
<Icon
className = { classes.prejoinPreviewDropdownIcon }
color = '#1C2025'
size = { 24 }
src = { icon } />
{label}
</div>
);
};
export default DropdownButton;

View File

@ -13,6 +13,8 @@ import { ActionButton, InputField, PreMeetingScreen } from '../../../base/premee
import { connect } from '../../../base/redux';
import { getDisplayName, updateSettings } from '../../../base/settings';
import { getLocalJitsiVideoTrack } from '../../../base/tracks';
import Button from '../../../base/ui/components/web/Button';
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
import {
joinConference as joinConferenceAction,
joinConferenceWithoutAudio as joinConferenceWithoutAudioAction,
@ -26,7 +28,6 @@ import {
isPrejoinDisplayNameVisible
} from '../../functions';
import DropdownButton from './DropdownButton';
import JoinByPhoneDialog from './dialogs/JoinByPhoneDialog';
type Props = {
@ -56,6 +57,11 @@ type Props = {
*/
joinConferenceWithoutAudio: Function,
/**
* Whether conference join is in progress.
*/
joiningInProgress: boolean,
/**
* The name of the user that is about to join.
*/
@ -114,11 +120,6 @@ type Props = {
type State = {
/**
* Flag controlling the visibility of the error label.
*/
showError: boolean,
/**
* Flag controlling the visibility of the 'join by phone' buttons.
*/
@ -138,7 +139,6 @@ class Prejoin extends Component<Props, State> {
super(props);
this.state = {
showError: false,
showJoinByPhoneButtons: false
};
@ -165,14 +165,8 @@ class Prejoin extends Component<Props, State> {
*/
_onJoinButtonClick() {
if (this.props.showErrorOnJoin) {
this.setState({
showError: true
});
return;
}
this.setState({ showError: false });
this.props.joinConference();
}
@ -304,20 +298,20 @@ class Prejoin extends Component<Props, State> {
const noAudio = {
key: 'no-audio',
dataTestId: 'prejoin.joinWithoutAudio',
testId: 'prejoin.joinWithoutAudio',
icon: IconVolumeOff,
label: t('prejoin.joinWithoutAudio'),
onButtonClick: joinConferenceWithoutAudio,
onKeyPressed: this._onJoinConferenceWithoutAudioKeyPress
onClick: joinConferenceWithoutAudio,
onKeyPress: this._onJoinConferenceWithoutAudioKeyPress
};
const byPhone = {
key: 'by-phone',
dataTestId: 'prejoin.joinByPhone',
testId: 'prejoin.joinByPhone',
icon: IconPhoneRinging,
label: t('prejoin.joinAudioByPhone'),
onButtonClick: this._showDialog,
onKeyPressed: this._showDialogKeyPress
onClick: this._showDialog,
onKeyPress: this._showDialogKeyPress
};
return {
@ -338,12 +332,14 @@ class Prejoin extends Component<Props, State> {
hasJoinByPhoneButton,
joinConference,
joinConferenceWithoutAudio,
joiningInProgress,
name,
participantId,
prejoinConfig,
readOnlyName,
showCameraPreview,
showDialog,
showErrorOnJoin,
t,
videoTrack
} = this.props;
@ -359,7 +355,7 @@ class Prejoin extends Component<Props, State> {
extraButtonsToRender = extraButtonsToRender.filter((btn: Object) => btn.key !== 'by-phone');
}
const hasExtraJoinButtons = Boolean(extraButtonsToRender.length);
const { showJoinByPhoneButtons, showError } = this.state;
const { showJoinByPhoneButtons } = this.state;
return (
<PreMeetingScreen
@ -373,8 +369,8 @@ class Prejoin extends Component<Props, State> {
{this.showDisplayNameField ? (<InputField
autoComplete = { 'name' }
autoFocus = { true }
className = { showError ? 'error' : '' }
hasError = { showError }
className = { showErrorOnJoin ? 'error' : '' }
hasError = { showErrorOnJoin }
onChange = { _setName }
onSubmit = { joinConference }
placeHolder = { t('dialog.enterDisplayName') }
@ -391,7 +387,7 @@ class Prejoin extends Component<Props, State> {
</div>
)}
{showError && <div
{showErrorOnJoin && <div
className = 'prejoin-error'
data-testid = 'prejoin.errorMessage'>{t('prejoin.errorMissingName')}</div>}
@ -399,8 +395,11 @@ class Prejoin extends Component<Props, State> {
<InlineDialog
content = { hasExtraJoinButtons && <div className = 'prejoin-preview-dropdown-btns'>
{extraButtonsToRender.map(({ key, ...rest }: Object) => (
<DropdownButton
<Button
disabled = { joiningInProgress }
fullWidth = { true }
key = { key }
type = { BUTTON_TYPES.SECONDARY }
{ ...rest } />
))}
</div> }
@ -411,6 +410,7 @@ class Prejoin extends Component<Props, State> {
ariaDropDownLabel = { t('prejoin.joinWithoutAudio') }
ariaLabel = { t('prejoin.joinMeeting') }
ariaPressed = { showJoinByPhoneButtons }
disabled = { joiningInProgress }
hasOptions = { hasExtraJoinButtons }
onClick = { _onJoinButtonClick }
onKeyPress = { _onJoinKeyPress }
@ -444,11 +444,13 @@ function mapStateToProps(state): Object {
const name = getDisplayName(state);
const showErrorOnJoin = isDisplayNameRequired(state) && !name;
const { id: participantId } = getLocalParticipant(state);
const { joiningInProgress } = state['features/prejoin'];
return {
canEditDisplayName: isPrejoinDisplayNameVisible(state),
deviceStatusVisible: isDeviceStatusVisible(state),
hasJoinByPhoneButton: isJoinByPhoneButtonVisible(state),
joiningInProgress,
name,
participantId,
prejoinConfig: state['features/base/config'].prejoinConfig,