Skip to content

Commit

Permalink
feat(visitors) add info dialog (jitsi#14926)
Browse files Browse the repository at this point in the history
  • Loading branch information
mihhu authored Jul 19, 2024
1 parent 1376f59 commit 94b6808
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 8 deletions.
7 changes: 7 additions & 0 deletions lang/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
"Remove": "Remove",
"Share": "Share",
"Submit": "Submit",
"Understood": "Understood",
"WaitForHostMsg": "The conference has not yet started because no moderators have yet arrived. If you'd like to become a moderator please log-in. Otherwise, please wait.",
"WaitForHostNoAuthMsg": "The conference has not yet started because no moderators have yet arrived. Please wait.",
"WaitingForHostButton": "Wait for moderator",
Expand Down Expand Up @@ -1492,6 +1493,12 @@
},
"visitors": {
"chatIndicator": "(visitor)",
"joinMeeting": {
"description": "You're currently an observer in this conference.",
"raiseHand": "Raise your hand",
"title": "Joining meeting",
"wishToSpeak": "If you wish to speak, please raise your hand below and wait for the moderator's approval."
},
"labelTooltip": "Number of visitors: {{count}}",
"notification": {
"demoteDescription": "Sent here by {{actor}}, raise your hand to participate",
Expand Down
7 changes: 2 additions & 5 deletions react/features/base/ui/components/web/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,9 @@ const Dialog = ({
}, [ onCancel ]);

const submit = useCallback(() => {
if (onSubmit && (
(document.activeElement && !operatesWithEnterKey(document.activeElement))
|| !document.activeElement
)) {
if ((document.activeElement && !operatesWithEnterKey(document.activeElement)) || !document.activeElement) {
!disableAutoHideOnSubmit && dispatch(hideDialog());
onSubmit();
onSubmit?.();
}
}, [ onSubmit ]);

Expand Down
32 changes: 31 additions & 1 deletion react/features/reactions/components/native/RaiseHandButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ interface IProps extends AbstractButtonProps {
*/
_raisedHand: boolean;

/**
* Whether or not the click is disabled.
*/
disableClick?: boolean;

/**
* Used to close the overflow menu after raise hand is clicked.
*/
Expand Down Expand Up @@ -75,8 +80,14 @@ class RaiseHandButton extends Component<IProps> {
* @returns {void}
*/
_onClick() {
const { disableClick, onCancel } = this.props;

if (disableClick) {
return;
}

this._toggleRaisedHand();
this.props.onCancel();
onCancel();
}

/**
Expand Down Expand Up @@ -159,4 +170,23 @@ function _mapStateToProps(state: IReduxState) {
};
}

/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {IProps}
*/
function _standaloneMapStateToProps(state: IReduxState) {
const _enabled = getFeatureFlag(state, RAISE_HAND_ENABLED, true);

return {
_enabled
};
}

const StandaloneRaiseHandButton = translate(connect(_standaloneMapStateToProps)(RaiseHandButton));

export { StandaloneRaiseHandButton };

export default translate(connect(_mapStateToProps)(RaiseHandButton));
20 changes: 18 additions & 2 deletions react/features/reactions/components/web/RaiseHandButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { connect } from 'react-redux';

import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { IReduxState, IStore } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconRaiseHand } from '../../../base/icons/svg';
import { raiseHand } from '../../../base/participants/actions';
Expand All @@ -15,6 +15,16 @@ import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/too
*/
interface IProps extends AbstractButtonProps {

/**
* Whether or not the click is disabled.
*/
disableClick?: boolean;

/**
* Redux dispatch function.
*/
dispatch: IStore['dispatch'];

/**
* Whether or not the hand is raised.
*/
Expand Down Expand Up @@ -51,7 +61,11 @@ class RaiseHandButton extends AbstractButton<IProps> {
* @returns {void}
*/
_handleClick() {
const { dispatch, raisedHand } = this.props;
const { disableClick, dispatch, raisedHand } = this.props;

if (disableClick) {
return;
}

sendAnalytics(createToolbarEvent(
'raise.hand',
Expand All @@ -76,4 +90,6 @@ const mapStateToProps = (state: IReduxState) => {
};
};

export { RaiseHandButton };

export default translate(connect(mapStateToProps)(RaiseHandButton));
1 change: 1 addition & 0 deletions react/features/visitors/components/index.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as JoinMeetingDialog } from './native/JoinMeetingDialog';
1 change: 1 addition & 0 deletions react/features/visitors/components/index.web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as JoinMeetingDialog } from './web/JoinMeetingDialog';
40 changes: 40 additions & 0 deletions react/features/visitors/components/native/JoinMeetingDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { View, ViewStyle } from 'react-native';
import Dialog from 'react-native-dialog';

import { StandaloneRaiseHandButton as RaiseHandButton } from '../../../reactions/components/native/RaiseHandButton';
import styles from '../../components/native/styles';

/**
* Component that renders the join meeting dialog for visitors.
*
* @returns {JSX.Element}
*/
export default function JoinMeetingDialog() {
const { t } = useTranslation();
const [ visible, setVisible ] = useState(true);

const closeDialog = useCallback(() => {
setVisible(false);
}, []);

return (
<Dialog.Container
coverScreen = { false }
visible = { visible }>
<Dialog.Title>{ t('visitors.joinMeeting.title') }</Dialog.Title>
<Dialog.Description>
{ t('visitors.joinMeeting.description') }
<View style = { styles.raiseHandButton as ViewStyle }>
{/* @ts-ignore */}
<RaiseHandButton disableClick = { true } />
</View>
</Dialog.Description>
<Dialog.Description>{t('visitors.joinMeeting.wishToSpeak')}</Dialog.Description>
<Dialog.Button
label = { t('dialog.Understood') }
onPress = { closeDialog } />
</Dialog.Container>
);
}
12 changes: 12 additions & 0 deletions react/features/visitors/components/native/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* The styles of the feature visitors.
*/
export default {

raiseHandButton: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%'
}
};
75 changes: 75 additions & 0 deletions react/features/visitors/components/web/JoinMeetingDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { noop } from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';

import { IconArrowUp } from '../../../base/icons/svg';
import ToolboxButtonWithPopup from '../../../base/toolbox/components/web/ToolboxButtonWithPopup';
import Dialog from '../../../base/ui/components/web/Dialog';
import { RaiseHandButton } from '../../../reactions/components/web/RaiseHandButton';

const useStyles = makeStyles()(theme => {
return {
raiseHand: {
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
marginTop: theme.spacing(3),
marginBottom: theme.spacing(3),
pointerEvents: 'none'
},
raiseHandTooltip: {
border: '1px solid #444',
borderRadius: theme.shape.borderRadius,
paddingBottom: theme.spacing(1),
paddingTop: theme.spacing(1),
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2)
},
raiseHandButton: {
display: 'inline-block',
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
position: 'relative'
}
};
});

/**
* Component that renders the join meeting dialog for visitors.
*
* @returns {JSX.Element}
*/
export default function JoinMeetingDialog() {
const { t } = useTranslation();
const { classes } = useStyles();

return (
<Dialog
cancel = {{ hidden: true }}
ok = {{ translationKey: 'dialog.Understood' }}
titleKey = 'visitors.joinMeeting.title'>
<div className = 'join-meeting-dialog'>
<p>{t('visitors.joinMeeting.description')}</p>
<div className = { classes.raiseHand }>
<p className = { classes.raiseHandTooltip }>{t('visitors.joinMeeting.raiseHand')}</p>
<div className = { classes.raiseHandButton }>
<ToolboxButtonWithPopup
icon = { IconArrowUp }
iconDisabled = { false }
onPopoverClose = { noop }
onPopoverOpen = { noop }
popoverContent = { null }
visible = { false }>
{/* @ts-ignore */}
<RaiseHandButton
disableClick = { true }
raisedHand = { true } />
</ToolboxButtonWithPopup>
</div>
</div>
<p>{t('visitors.joinMeeting.wishToSpeak')}</p>
</div>
</Dialog>
);
}
4 changes: 4 additions & 0 deletions react/features/visitors/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { SET_CONFIG } from '../base/config/actionTypes';
import { CONNECTION_FAILED } from '../base/connection/actionTypes';
import { connect, setPreferVisitor } from '../base/connection/actions';
import { disconnect } from '../base/connection/actions.any';
import { openDialog } from '../base/dialog/actions';
import { JitsiConferenceEvents, JitsiConnectionErrors } from '../base/lib-jitsi-meet';
import { PARTICIPANT_UPDATED } from '../base/participants/actionTypes';
import { raiseHand } from '../base/participants/actions';
Expand Down Expand Up @@ -48,6 +49,7 @@ import {
updateVisitorsCount,
updateVisitorsInQueueCount
} from './actions';
import { JoinMeetingDialog } from './components';
import { getPromotionRequests, getVisitorsCount, getVisitorsInQueueCount } from './functions';
import logger from './logger';
import { WebsocketClient } from './websocket-client';
Expand All @@ -70,6 +72,8 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
const { conference } = action;

if (getState()['features/visitors'].iAmVisitor) {
dispatch(openDialog(JoinMeetingDialog));

const { demoteActorDisplayName } = getState()['features/visitors'];

dispatch(setVisitorDemoteActor(undefined));
Expand Down

0 comments on commit 94b6808

Please sign in to comment.