ref(toolbar) Move getButtons to functions (#13502)

Move visible logic inside each button
Move click functionality inside each button
Extract getButtons function from Toolbox components to functions file
pull/13506/head jitsi-meet_8765
Robert Pintilii 2 years ago committed by GitHub
parent 699b797e0f
commit 2d8014775a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      react/features/chat/components/web/ChatButton.tsx
  2. 17
      react/features/embed-meeting/components/EmbedMeetingButton.ts
  3. 5
      react/features/feedback/components/FeedbackButton.web.ts
  4. 17
      react/features/keyboard-shortcuts/components/web/KeyboardShortcutsButton.ts
  5. 20
      react/features/participants-pane/components/web/ParticipantsPaneButton.tsx
  6. 19
      react/features/reactions/components/web/RaiseHandButton.ts
  7. 26
      react/features/reactions/components/web/RaiseHandContainerButtons.tsx
  8. 68
      react/features/reactions/components/web/ReactionsMenuButton.tsx
  9. 6
      react/features/screen-share/components/web/ShareAudioButton.ts
  10. 16
      react/features/speaker-stats/components/web/SpeakerStatsButton.tsx
  11. 14
      react/features/toolbox/actions.web.ts
  12. 26
      react/features/toolbox/components/web/FullscreenButton.ts
  13. 16
      react/features/toolbox/components/web/LinkToSalesforceButton.ts
  14. 5
      react/features/toolbox/components/web/ProfileButton.ts
  15. 24
      react/features/toolbox/components/web/ShareDesktopButton.ts
  16. 737
      react/features/toolbox/components/web/Toolbox.tsx
  17. 285
      react/features/toolbox/functions.web.ts
  18. 8
      react/features/toolbox/types.ts
  19. 23
      react/features/video-quality/components/VideoQualityButton.web.ts
  20. 4
      react/features/virtual-background/components/VideoBackgroundButton.ts
  21. 5
      react/features/whiteboard/components/web/WhiteboardButton.tsx

@ -1,10 +1,14 @@
import React from 'react';
import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconMessage } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { closeOverflowMenuIfOpen } from '../../../toolbox/actions.web';
import { toggleChat } from '../../actions.web';
import ChatCounter from './ChatCounter';
@ -59,6 +63,24 @@ class ChatButton extends AbstractButton<IProps> {
</div>
);
}
/**
* Handles clicking the button, and toggles the chat.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch } = this.props;
sendAnalytics(createToolbarEvent(
'toggle.chat',
{
enable: !this.props._chatOpen
}));
dispatch(closeOverflowMenuIfOpen());
dispatch(toggleChat());
}
}
/**

@ -2,10 +2,13 @@ import { connect } from 'react-redux';
import { createToolbarEvent } from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { IReduxState } from '../../app/types';
import { openDialog } from '../../base/dialog/actions';
import { isMobileBrowser } from '../../base/environment/utils';
import { translate } from '../../base/i18n/functions';
import { IconCode } from '../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
import { isVpaasMeeting } from '../../jaas/functions';
import EmbedMeetingDialog from './EmbedMeetingDialog';
@ -32,4 +35,16 @@ class EmbedMeetingButton extends AbstractButton<AbstractButtonProps> {
}
}
export default translate(connect()(EmbedMeetingButton));
/**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @returns {Object}
*/
const mapStateToProps = (state: IReduxState) => {
return {
visible: !isVpaasMeeting(state) && !isMobileBrowser()
};
};
export default translate(connect(mapStateToProps)(EmbedMeetingButton));

@ -45,8 +45,11 @@ class FeedbackButton extends AbstractButton<IProps> {
}
const mapStateToProps = (state: IReduxState) => {
const { callStatsID } = state['features/base/config'];
return {
_conference: state['features/base/conference'].conference
_conference: state['features/base/conference'].conference,
visible: Boolean(callStatsID)
};
};

@ -2,11 +2,14 @@ import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { isMobileBrowser } from '../../../base/environment/utils';
import { translate } from '../../../base/i18n/functions';
import { IconShortcuts } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { openSettingsDialog } from '../../../settings/actions';
import { SETTINGS_TABS } from '../../../settings/constants';
import { areKeyboardShortcutsEnabled } from '../../functions';
/**
* Implementation of a button for opening keyboard shortcuts dialog.
@ -31,4 +34,16 @@ class KeyboardShortcutsButton extends AbstractButton<AbstractButtonProps> {
}
}
export default translate(connect()(KeyboardShortcutsButton));
/**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @returns {Object}
*/
const mapStateToProps = (state: IReduxState) => {
return {
visible: !isMobileBrowser() && areKeyboardShortcutsEnabled(state)
};
};
export default translate(connect(mapStateToProps)(KeyboardShortcutsButton));

@ -5,6 +5,10 @@ import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconUsers } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import {
close as closeParticipantsPane,
open as openParticipantsPane
} from '../../../participants-pane/actions.web';
import ParticipantsCounter from './ParticipantsCounter';
@ -41,6 +45,22 @@ class ParticipantsPaneButton extends AbstractButton<IProps> {
return this.props._isOpen;
}
/**
* Handles clicking the button, and toggles the participants pane.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch, _isOpen } = this.props;
if (_isOpen) {
dispatch(closeParticipantsPane());
} else {
dispatch(openParticipantsPane());
}
}
/**
* Overrides AbstractButton's {@link Component#render()}.
*

@ -1,8 +1,11 @@
import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconRaiseHand } from '../../../base/icons/svg';
import { raiseHand } from '../../../base/participants/actions';
import { getLocalParticipant, hasRaisedHand } from '../../../base/participants/functions';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
@ -40,6 +43,22 @@ class RaiseHandButton extends AbstractButton<IProps> {
_isToggled() {
return this.props.raisedHand;
}
/**
* Handles clicking the button, and toggles the raise hand.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch, raisedHand } = this.props;
sendAnalytics(createToolbarEvent(
'raise.hand',
{ enable: !raisedHand }));
dispatch(raiseHand(!raisedHand));
}
}

@ -0,0 +1,26 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { isMobileBrowser } from '../../../base/environment/utils';
import { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { isReactionsButtonEnabled, isReactionsEnabled } from '../../functions.web';
import RaiseHandButton from './RaiseHandButton';
import ReactionsMenuButton from './ReactionsMenuButton';
const RaiseHandContainerButton = (props: AbstractButtonProps) => {
const reactionsButtonEnabled = useSelector(isReactionsButtonEnabled);
const reactionsEnabled = useSelector(isReactionsEnabled);
const isNarrowLayout = useSelector((state: IReduxState) => state['features/base/responsive-ui'].isNarrowLayout);
const showReactionsAsPartOfRaiseHand
= !reactionsButtonEnabled && reactionsEnabled && !isNarrowLayout && !isMobileBrowser();
return showReactionsAsPartOfRaiseHand
? <ReactionsMenuButton
{ ...props }
showRaiseHand = { true } />
: <RaiseHandButton { ...props } />;
};
export default RaiseHandContainerButton;

@ -1,11 +1,15 @@
import React, { ReactElement, useCallback } from 'react';
import React, { ReactElement, useCallback, useMemo } from 'react';
import { WithTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { connect, useSelector } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState, IStore } from '../../../app/types';
import { isMobileBrowser } from '../../../base/environment/utils';
import { translate } from '../../../base/i18n/functions';
import { IconArrowUp, IconFaceSmile } from '../../../base/icons/svg';
import { raiseHand } from '../../../base/participants/actions';
import { getLocalParticipant, hasRaisedHand } from '../../../base/participants/functions';
import AbstractButton, { type IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import ToolboxButtonWithPopup from '../../../base/toolbox/components/web/ToolboxButtonWithPopup';
import { toggleReactionsMenuVisibility } from '../../actions.web';
@ -30,6 +34,11 @@ interface IProps extends WithTranslation {
*/
_reactionsButtonEnabled: boolean;
/**
* Whether or not the reactions are enabled.
*/
_reactionsEnabled: boolean;
/**
* The button's key.
*/
@ -40,11 +49,6 @@ interface IProps extends WithTranslation {
*/
dispatch: IStore['dispatch'];
/**
* Click handler for raise hand functionality.
*/
handleClick: Function;
/**
* Whether or not it's narrow mode or mobile browser.
*/
@ -65,6 +69,11 @@ interface IProps extends WithTranslation {
* The array of reactions to be displayed.
*/
reactionsQueue: Array<IReactionEmojiProps>;
/**
* Whether or not to show the raise hand button.
*/
showRaiseHand?: boolean;
}
@ -88,14 +97,15 @@ const ReactionsButton = translate(connect()(ReactionsButtonImpl));
*/
function ReactionsMenuButton({
_reactionsButtonEnabled,
_reactionsEnabled,
_isMobile,
buttonKey,
dispatch,
handleClick,
isOpen,
isNarrow,
notifyMode,
reactionsQueue,
showRaiseHand,
t
}: IProps) {
const toggleReactionsMenu = useCallback(() => {
@ -110,26 +120,27 @@ function ReactionsMenuButton({
isOpen && toggleReactionsMenu();
}, [ isOpen, toggleReactionsMenu ]);
const localParticipant = useSelector(getLocalParticipant);
const raisedHand = useMemo(() => hasRaisedHand(localParticipant), [ localParticipant ]);
const handleClick = useCallback(() => {
sendAnalytics(createToolbarEvent(
'raise.hand',
{ enable: !raisedHand }));
dispatch(raiseHand(!raisedHand));
}, [ raisedHand ]);
if (!showRaiseHand && (!_reactionsButtonEnabled || !_reactionsEnabled)) {
return null;
}
const reactionsMenu = (<div className = 'reactions-menu-container'>
<ReactionsMenu parent = { IReactionsMenuParent.Button } />
</div>);
let content: ReactElement | null = null;
if (_reactionsButtonEnabled) {
content = (
<ToolboxButtonWithPopup
ariaLabel = { t('toolbar.accessibilityLabel.reactionsMenu') }
onPopoverClose = { closeReactionsMenu }
onPopoverOpen = { openReactionsMenu }
popoverContent = { reactionsMenu }
trigger = { _isMobile ? 'click' : undefined }
visible = { isOpen }>
<ReactionsButton
buttonKey = { buttonKey }
notifyMode = { notifyMode } />
</ToolboxButtonWithPopup>);
} else {
if (showRaiseHand) {
content = isNarrow
? (
<RaiseHandButton
@ -150,6 +161,19 @@ function ReactionsMenuButton({
handleClick = { handleClick }
notifyMode = { notifyMode } />
</ToolboxButtonWithPopup>);
} else {
content = (
<ToolboxButtonWithPopup
ariaLabel = { t('toolbar.accessibilityLabel.reactionsMenu') }
onPopoverClose = { closeReactionsMenu }
onPopoverOpen = { openReactionsMenu }
popoverContent = { reactionsMenu }
trigger = { _isMobile ? 'click' : undefined }
visible = { isOpen }>
<ReactionsButton
buttonKey = { buttonKey }
notifyMode = { notifyMode } />
</ToolboxButtonWithPopup>);
}
return (

@ -3,10 +3,11 @@ import { connect } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconVolumeOff, IconVolumeUp } from '../../../base/icons/svg';
import JitsiMeetJS from '../../../base/lib-jitsi-meet';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { setOverflowMenuVisible } from '../../../toolbox/actions.web';
import { startAudioScreenShareFlow } from '../../actions.web';
import { isAudioOnlySharing } from '../../functions';
import { isAudioOnlySharing, isScreenAudioSupported } from '../../functions';
interface IProps extends AbstractButtonProps {
@ -62,7 +63,8 @@ class ShareAudioButton extends AbstractButton<IProps> {
function _mapStateToProps(state: IReduxState) {
return {
_isAudioOnlySharing: Boolean(isAudioOnlySharing(state))
_isAudioOnlySharing: Boolean(isAudioOnlySharing(state)),
visible: JitsiMeetJS.isDesktopSharingEnabled() && isScreenAudioSupported()
};
}

@ -2,8 +2,10 @@ import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { openDialog } from '../../../base/dialog/actions';
import { translate } from '../../../base/i18n/functions';
import { isSpeakerStatsDisabled } from '../../functions';
import AbstractSpeakerStatsButton from '../AbstractSpeakerStatsButton';
import SpeakerStats from './SpeakerStats';
@ -28,4 +30,16 @@ class SpeakerStatsButton extends AbstractSpeakerStatsButton {
}
}
export default translate(connect()(SpeakerStatsButton));
/**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @returns {Object}
*/
const mapStateToProps = (state: IReduxState) => {
return {
visible: !isSpeakerStatsDisabled(state)
};
};
export default translate(connect(mapStateToProps)(SpeakerStatsButton));

@ -264,3 +264,17 @@ export function setToolboxTimeout(handler: Function, timeoutMS: number) {
});
};
}
/**
* Closes the overflow menu if opened.
*
* @private
* @returns {void}
*/
export function closeOverflowMenuIfOpen() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const { overflowMenuVisible } = getState()['features/toolbox'];
overflowMenuVisible && dispatch(setOverflowMenuVisible(false));
};
}

@ -1,9 +1,13 @@
import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { isIosMobileBrowser } from '../../../base/environment/utils';
import { translate } from '../../../base/i18n/functions';
import { IconEnterFullscreen, IconExitFullscreen } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { closeOverflowMenuIfOpen, setFullScreen } from '../../actions.web';
interface IProps extends AbstractButtonProps {
@ -36,6 +40,25 @@ class FullscreenButton extends AbstractButton<IProps> {
_isToggled() {
return this.props._fullScreen;
}
/**
* Handles clicking the button, and toggles fullscreen.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch, _fullScreen } = this.props;
sendAnalytics(createToolbarEvent(
'toggle.fullscreen',
{
enable: !_fullScreen
}));
dispatch(closeOverflowMenuIfOpen());
dispatch(setFullScreen(!_fullScreen));
}
}
/**
@ -46,7 +69,8 @@ class FullscreenButton extends AbstractButton<IProps> {
*/
const mapStateToProps = (state: IReduxState) => {
return {
_fullScreen: state['features/toolbox'].fullScreen
_fullScreen: state['features/toolbox'].fullScreen,
visible: !isIosMobileBrowser()
};
};

@ -2,11 +2,13 @@ import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { openDialog } from '../../../base/dialog/actions';
import { translate } from '../../../base/i18n/functions';
import { IconCloudUpload } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import SalesforceLinkDialog from '../../../salesforce/components/web/SalesforceLinkDialog';
import { isSalesforceEnabled } from '../../../salesforce/functions';
/**
* Implementation of a button for opening the Salesforce link dialog.
@ -31,4 +33,16 @@ class LinkToSalesforce extends AbstractButton<AbstractButtonProps> {
}
}
export default translate(connect()(LinkToSalesforce));
/**
* Function that maps parts of Redux state tree into component props.
*
* @param {Object} state - Redux state.
* @returns {Object}
*/
const mapStateToProps = (state: IReduxState) => {
return {
visible: isSalesforceEnabled(state)
};
};
export default translate(connect(mapStateToProps)(LinkToSalesforce));

@ -103,13 +103,14 @@ class ProfileButton extends AbstractButton<IProps> {
* @returns {Object}
*/
const mapStateToProps = (state: IReduxState) => {
const { defaultLocalDisplayName } = state['features/base/config'];
const { defaultLocalDisplayName, disableProfile } = state['features/base/config'];
return {
_defaultLocalDisplayName: defaultLocalDisplayName ?? '',
_localParticipant: getLocalParticipant(state),
_unclickable: !interfaceConfig.SETTINGS_SECTIONS.includes('profile'),
customClass: 'profile-button-avatar'
customClass: 'profile-button-avatar',
visible: !disableProfile
};
};

@ -1,11 +1,15 @@
import { connect } from 'react-redux';
import { createToolbarEvent } from '../../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconScreenshare, IconStopScreenshare } from '../../../base/icons/svg';
import JitsiMeetJS from '../../../base/lib-jitsi-meet/_';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { startScreenShareFlow } from '../../../screen-share/actions.web';
import { isScreenVideoShared } from '../../../screen-share/functions';
import { closeOverflowMenuIfOpen } from '../../actions.web';
import { isDesktopShareButtonDisabled } from '../../functions';
interface IProps extends AbstractButtonProps {
@ -72,6 +76,23 @@ class ShareDesktopButton extends AbstractButton<IProps> {
_isDisabled() {
return !this.props._desktopSharingEnabled;
}
/**
* Handles clicking the button, and toggles the chat.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch, _screensharing } = this.props;
sendAnalytics(createToolbarEvent(
'toggle.screen.sharing',
{ enable: !_screensharing }));
dispatch(closeOverflowMenuIfOpen());
dispatch(startScreenShareFlow(!_screensharing));
}
}
/**
@ -88,7 +109,8 @@ const mapStateToProps = (state: IReduxState) => {
return {
_desktopSharingEnabled: desktopSharingEnabled,
_screensharing: isScreenVideoShared(state)
_screensharing: isScreenVideoShared(state),
visible: JitsiMeetJS.isDesktopSharingEnabled()
};
};

File diff suppressed because it is too large Load Diff

@ -4,10 +4,43 @@ import { hasAvailableDevices } from '../base/devices/functions';
import { MEET_FEATURES } from '../base/jwt/constants';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { IGUMPendingState } from '../base/media/types';
import ChatButton from '../chat/components/web/ChatButton';
import EmbedMeetingButton from '../embed-meeting/components/EmbedMeetingButton';
import SharedDocumentButton from '../etherpad/components/SharedDocumentButton.web';
import FeedbackButton from '../feedback/components/FeedbackButton.web';
import InviteButton from '../invite/components/add-people-dialog/web/InviteButton';
import KeyboardShortcutsButton from '../keyboard-shortcuts/components/web/KeyboardShortcutsButton';
import NoiseSuppressionButton from '../noise-suppression/components/NoiseSuppressionButton';
import ParticipantsPaneButton from '../participants-pane/components/web/ParticipantsPaneButton';
import RaiseHandContainerButton from '../reactions/components/web/RaiseHandContainerButtons';
import ReactionsMenuButton from '../reactions/components/web/ReactionsMenuButton';
import LiveStreamButton from '../recording/components/LiveStream/web/LiveStreamButton';
import RecordButton from '../recording/components/Recording/web/RecordButton';
import ShareAudioButton from '../screen-share/components/web/ShareAudioButton';
import { isScreenMediaShared } from '../screen-share/functions';
import SecurityDialogButton from '../security/components/security-dialog/web/SecurityDialogButton';
import SettingsButton from '../settings/components/web/SettingsButton';
import SharedVideoButton from '../shared-video/components/web/SharedVideoButton';
import SpeakerStatsButton from '../speaker-stats/components/web/SpeakerStatsButton';
import ClosedCaptionButton from '../subtitles/components/web/ClosedCaptionButton';
import TileViewButton from '../video-layout/components/TileViewButton';
import VideoQualityButton from '../video-quality/components/VideoQualityButton.web';
import VideoBackgroundButton from '../virtual-background/components/VideoBackgroundButton';
import WhiteboardButton from '../whiteboard/components/web/WhiteboardButton';
import { isWhiteboardVisible } from '../whiteboard/functions';
import DownloadButton from './components/DownloadButton';
import HelpButton from './components/HelpButton';
import AudioSettingsButton from './components/web/AudioSettingsButton';
import CustomOptionButton from './components/web/CustomOptionButton';
import FullscreenButton from './components/web/FullscreenButton';
import LinkToSalesforceButton from './components/web/LinkToSalesforceButton';
import ProfileButton from './components/web/ProfileButton';
import ShareDesktopButton from './components/web/ShareDesktopButton';
import ToggleCameraButton from './components/web/ToggleCameraButton';
import VideoSettingsButton from './components/web/VideoSettingsButton';
import { TOOLBAR_TIMEOUT } from './constants';
import { IToolboxButton } from './types';
export * from './functions.any';
@ -158,3 +191,255 @@ export function getToolbarTimeout(state: IReduxState) {
return toolbarConfig?.timeout || TOOLBAR_TIMEOUT;
}
/**
* Returns all buttons that could be rendered.
*
* @param {Object} _customToolbarButtons - An array containing custom buttons objects.
* @returns {Object} The button maps mainMenuButtons and overflowMenuButtons.
*/
export function getAllToolboxButtons(_customToolbarButtons?: {
icon: string;
id: string;
text: string;
}[]): { [key: string]: IToolboxButton; } {
const microphone = {
key: 'microphone',
Content: AudioSettingsButton,
group: 0
};
const camera = {
key: 'camera',
Content: VideoSettingsButton,
group: 0
};
const profile = {
key: 'profile',
Content: ProfileButton,
group: 1
};
const chat = {
key: 'chat',
Content: ChatButton,
group: 2
};
const desktop = {
key: 'desktop',
Content: ShareDesktopButton,
group: 2
};
// In Narrow layout and mobile web we are using drawer for popups and that is why it is better to include
// all forms of reactions in the overflow menu. Otherwise the toolbox will be hidden and the reactions popup
// misaligned.
const raisehand = {
key: 'raisehand',
Content: RaiseHandContainerButton,
group: 2
};
const reactions = {
key: 'reactions',
Content: ReactionsMenuButton,
group: 2
};
const participants = {
key: 'participants-pane',
Content: ParticipantsPaneButton,
group: 2
};
const invite = {
key: 'invite',
Content: InviteButton,
group: 2
};
const tileview = {
key: 'tileview',
Content: TileViewButton,
group: 2
};
const toggleCamera = {
key: 'toggle-camera',
Content: ToggleCameraButton,
group: 2
};
const videoQuality = {
key: 'videoquality',
Content: VideoQualityButton,
group: 2
};
const fullscreen = {
key: 'fullscreen',
Content: FullscreenButton,
group: 2
};
const security = {
key: 'security',
alias: 'info',
Content: SecurityDialogButton,
group: 2
};
const cc = {
key: 'closedcaptions',
Content: ClosedCaptionButton,
group: 2
};
const recording = {
key: 'recording',
Content: RecordButton,
group: 2
};
const livestreaming = {
key: 'livestreaming',
Content: LiveStreamButton,
group: 2
};
const linkToSalesforce = {
key: 'linktosalesforce',
Content: LinkToSalesforceButton,
group: 2
};
const shareVideo = {
key: 'sharedvideo',
Content: SharedVideoButton,
group: 3
};
const shareAudio = {
key: 'shareaudio',
Content: ShareAudioButton,
group: 3
};
const noiseSuppression = {
key: 'noisesuppression',
Content: NoiseSuppressionButton,
group: 3
};
const whiteboard = {
key: 'whiteboard',
Content: WhiteboardButton,
group: 3
};
const etherpad = {
key: 'etherpad',
Content: SharedDocumentButton,
group: 3
};
const virtualBackground = {
key: 'select-background',
Content: VideoBackgroundButton,
group: 3
};
const speakerStats = {
key: 'stats',
Content: SpeakerStatsButton,
group: 3
};
const settings = {
key: 'settings',
Content: SettingsButton,
group: 4
};
const shortcuts = {
key: 'shortcuts',
Content: KeyboardShortcutsButton,
group: 4
};
const embed = {
key: 'embedmeeting',
Content: EmbedMeetingButton,
group: 4
};
const feedback = {
key: 'feedback',
Content: FeedbackButton,
group: 4
};
const download = {
key: 'download',
Content: DownloadButton,
group: 4
};
const help = {
key: 'help',
Content: HelpButton,
group: 4
};
const customButtons = _customToolbarButtons?.reduce((prev, { icon, id, text }) => {
return {
...prev,
[id]: {
key: id,
Content: CustomOptionButton,
group: 4,
icon,
text
}
};
}, {});
return {
microphone,
camera,
profile,
desktop,
chat,
raisehand,
reactions,
participants,
invite,
tileview,
toggleCamera,
videoQuality,
fullscreen,
security,
cc,
recording,
livestreaming,
linkToSalesforce,
shareVideo,
shareAudio,
noiseSuppression,
whiteboard,
etherpad,
virtualBackground,
speakerStats,
settings,
shortcuts,
embed,
feedback,
download,
help,
...customButtons
};
}

@ -0,0 +1,8 @@
import { ComponentType } from 'react';
export interface IToolboxButton {
Content: ComponentType<any>;
alias?: string;
group: number;
key: string;
}

@ -1,7 +1,14 @@
import { connect } from 'react-redux';
import { createToolbarEvent } from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { openDialog } from '../../base/dialog/actions';
import { translate } from '../../base/i18n/functions';
import { IconPerformance } from '../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
import VideoQualityDialog from './VideoQualityDialog.web';
/**
* The type of the React {@code Component} props of
* {@link VideoQualityButton}.
@ -32,6 +39,20 @@ class VideoQualityButton extends AbstractButton<IProps> {
label = 'videoStatus.performanceSettings';
tooltip = 'videoStatus.performanceSettings';
icon = IconPerformance;
/**
* Handles clicking the button, and opens the video quality dialog.
*
* @private
* @returns {void}
*/
_handleClick() {
const { dispatch } = this.props;
sendAnalytics(createToolbarEvent('video.quality'));
dispatch(openDialog(VideoQualityDialog));
}
}
export default translate(VideoQualityButton);
export default connect()(translate(VideoQualityButton));

@ -1,9 +1,11 @@
import { connect } from 'react-redux';
import { IReduxState } from '../../app/types';
import { getMultipleVideoSendingSupportFeatureFlag } from '../../base/config/functions.any';
import { translate } from '../../base/i18n/functions';
import { IconImage } from '../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
import { isScreenVideoShared } from '../../screen-share/functions';
import { openSettingsDialog } from '../../settings/actions';
import { SETTINGS_TABS } from '../../settings/constants';
import { checkBlurSupport } from '../functions';
@ -67,7 +69,7 @@ function _mapStateToProps(state: IReduxState) {
return {
_isBackgroundEnabled: Boolean(state['features/virtual-background'].backgroundEffectEnabled),
visible: checkBlurSupport()
visible: checkBlurSupport() && getMultipleVideoSendingSupportFeatureFlag(state) && !isScreenVideoShared(state)
};
}

@ -6,7 +6,7 @@ import { IconWhiteboard, IconWhiteboardHide } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { setOverflowMenuVisible } from '../../../toolbox/actions.web';
import { setWhiteboardOpen } from '../../actions';
import { isWhiteboardVisible } from '../../functions';
import { isWhiteboardButtonVisible, isWhiteboardVisible } from '../../functions';
interface IProps extends AbstractButtonProps {
@ -63,7 +63,8 @@ class WhiteboardButton extends AbstractButton<IProps> {
*/
function _mapStateToProps(state: IReduxState) {
return {
_toggled: isWhiteboardVisible(state)
_toggled: isWhiteboardVisible(state),
visible: isWhiteboardButtonVisible(state)
};
}

Loading…
Cancel
Save