{
*/
render() {
const {
+ classes,
className,
+ color,
icon,
id,
+ onClick,
text
} = this.props;
-
- const labelClassName = icon ? 'label-text-with-icon' : '';
+ const labelClassName = clsx(
+ classes.label,
+ onClick && classes.clickable,
+ color && classes[color],
+ className
+ );
return (
+ className = { labelClassName }
+ id = { id }
+ onClick = { onClick }>
{ icon && }
- { text && {text} }
+ { text && {text} }
);
}
}
+
+export default withStyles(styles)(Label);
diff --git a/react/features/base/label/constants.js b/react/features/base/label/constants.js
new file mode 100644
index 000000000..4eaf920a0
--- /dev/null
+++ b/react/features/base/label/constants.js
@@ -0,0 +1,7 @@
+// @flow
+
+export const COLORS = {
+ white: 'white',
+ green: 'green',
+ red: 'red'
+};
diff --git a/react/features/conference/components/web/InsecureRoomNameLabel.js b/react/features/conference/components/web/InsecureRoomNameLabel.js
index 136d1fefe..048da241d 100644
--- a/react/features/conference/components/web/InsecureRoomNameLabel.js
+++ b/react/features/conference/components/web/InsecureRoomNameLabel.js
@@ -6,6 +6,7 @@ import React from 'react';
import { translate } from '../../../base/i18n';
import { IconWarning } from '../../../base/icons';
import { Label } from '../../../base/label';
+import { COLORS } from '../../../base/label/constants';
import { connect } from '../../../base/redux';
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
@@ -24,7 +25,7 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
content = { this.props.t('security.insecureRoomNameWarning') }
position = 'bottom'>
);
diff --git a/react/features/conference/components/web/ParticipantsCount.js b/react/features/conference/components/web/ParticipantsCount.js
index 95b5e0b6e..0805af417 100644
--- a/react/features/conference/components/web/ParticipantsCount.js
+++ b/react/features/conference/components/web/ParticipantsCount.js
@@ -6,6 +6,7 @@ import type { Dispatch } from 'redux';
import { openDialog } from '../../../base/dialog';
import { IconUserGroups } from '../../../base/icons';
import { Label } from '../../../base/label';
+import { COLORS } from '../../../base/label/constants';
import { getParticipantCount } from '../../../base/participants';
import { connect } from '../../../base/redux';
import { SpeakerStats } from '../../../speaker-stats';
@@ -79,14 +80,11 @@ class ParticipantsCount extends PureComponent {
}
return (
-
-
-
+
);
}
}
diff --git a/react/features/e2ee/components/E2EELabel.js b/react/features/e2ee/components/E2EELabel.js
index d95b7fea1..2ee97f016 100644
--- a/react/features/e2ee/components/E2EELabel.js
+++ b/react/features/e2ee/components/E2EELabel.js
@@ -5,6 +5,7 @@ import React, { Component } from 'react';
import { translate } from '../../base/i18n';
import { IconE2EE } from '../../base/icons';
import { Label } from '../../base/label';
+import { COLORS } from '../../base/label/constants';
import { connect } from '../../base/redux';
import { Tooltip } from '../../base/tooltip';
@@ -36,7 +37,7 @@ class E2EELabel extends Component {
content = { content }
position = { 'bottom' }>
);
diff --git a/react/features/video-quality/components/VideoQualityButton.web.js b/react/features/video-quality/components/VideoQualityButton.web.js
index 85b3b22c1..7c0ffe4cb 100644
--- a/react/features/video-quality/components/VideoQualityButton.web.js
+++ b/react/features/video-quality/components/VideoQualityButton.web.js
@@ -1,29 +1,8 @@
// @flow
import { translate } from '../../base/i18n';
-import {
- IconVideoQualityAudioOnly,
- IconVideoQualityHD,
- IconVideoQualityLD,
- IconVideoQualitySD
-} from '../../base/icons';
-import { connect } from '../../base/redux';
+import { IconGauge } from '../../base/icons';
import { AbstractButton, type AbstractButtonProps } from '../../base/toolbox/components';
-import { VIDEO_QUALITY_LEVELS } from '../constants';
-import { findNearestQualityLevel } from '../functions';
-
-/**
- * A map of of selectable receive resolutions to corresponding icons.
- *
- * @private
- * @type {Object}
- */
-const VIDEO_QUALITY_TO_ICON = {
- [VIDEO_QUALITY_LEVELS.ULTRA]: IconVideoQualityHD,
- [VIDEO_QUALITY_LEVELS.HIGH]: IconVideoQualityHD,
- [VIDEO_QUALITY_LEVELS.STANDARD]: IconVideoQualitySD,
- [VIDEO_QUALITY_LEVELS.LOW]: IconVideoQualityLD
-};
/**
* The type of the React {@code Component} props of
@@ -57,32 +36,10 @@ type Props = AbstractButtonProps & {
*/
class VideoQualityButton extends AbstractButton {
accessibilityLabel = 'toolbar.accessibilityLabel.callQuality';
- label = 'toolbar.callQuality';
- tooltip = 'toolbar.callQuality';
+ label = 'videoStatus.performanceSettings';
+ tooltip = 'videoStatus.performanceSettings';
+ icon = IconGauge;
- /**
- * Dynamically retrieves the icon.
- */
- get icon() {
- const { _audioOnly, _videoQuality } = this.props;
-
- const videoQualityLevel = findNearestQualityLevel(_videoQuality);
-
- const icon = _audioOnly || !videoQualityLevel
- ? IconVideoQualityAudioOnly
- : VIDEO_QUALITY_TO_ICON[videoQualityLevel];
-
- return icon;
- }
-
- /**
- * Required by linter due to AbstractButton overwritten prop being writable.
- *
- * @param {string} value - The icon value.
- */
- set icon(value) {
- return value;
- }
/**
* Handles clicking / pressing the button.
@@ -102,23 +59,4 @@ class VideoQualityButton extends AbstractButton {
}
}
-/**
- * Maps (parts of) the Redux state to the associated props for the
- * {@code VideoQualityButton} component.
- *
- * @param {Object} state - The Redux state.
- * @private
- * @returns {{
- * _audioOnly: boolean,
- * _videoQuality: number
- * }}
- */
-function _mapStateToProps(state) {
- return {
- _audioOnly: state['features/base/audio-only'].enabled,
- _videoQuality: state['features/video-quality'].preferredVideoQuality
- };
-}
-
-export default translate(
- connect(_mapStateToProps)(VideoQualityButton));
+export default translate(VideoQualityButton);
diff --git a/react/features/video-quality/components/VideoQualityLabel.native.js b/react/features/video-quality/components/VideoQualityLabel.native.js
index 637f98a17..2bb4d2f31 100644
--- a/react/features/video-quality/components/VideoQualityLabel.native.js
+++ b/react/features/video-quality/components/VideoQualityLabel.native.js
@@ -53,22 +53,4 @@ class VideoQualityLabel extends AbstractVideoQualityLabel {
}
}
-/**
- * Maps (parts of) the Redux state to the associated
- * {@code VideoQualityLabel}'s props.
- *
- * NOTE: This component has no props other than the abstract ones but keeping
- * the coding style the same for consistency reasons.
- *
- * @param {Object} state - The Redux state.
- * @private
- * @returns {{
- * }}
- */
-function _mapStateToProps(state: Object) {
- return {
- ..._abstractMapStateToProps(state)
- };
-}
-
-export default translate(connect(_mapStateToProps)(VideoQualityLabel));
+export default translate(connect(_abstractMapStateToProps)(VideoQualityLabel));
diff --git a/react/features/video-quality/components/VideoQualityLabel.web.js b/react/features/video-quality/components/VideoQualityLabel.web.js
index 0d1e69a97..80ade1aad 100644
--- a/react/features/video-quality/components/VideoQualityLabel.web.js
+++ b/react/features/video-quality/components/VideoQualityLabel.web.js
@@ -2,71 +2,40 @@
import React from 'react';
+import { openDialog } from '../../base/dialog';
import { translate } from '../../base/i18n';
+import { IconGauge } from '../../base/icons';
import { Label } from '../../base/label';
-import { MEDIA_TYPE } from '../../base/media';
import { connect } from '../../base/redux';
import { Tooltip } from '../../base/tooltip';
-import { getTrackByMediaTypeAndParticipant } from '../../base/tracks';
import { shouldDisplayTileView } from '../../video-layout';
import AbstractVideoQualityLabel, {
_abstractMapStateToProps,
type Props as AbstractProps
} from './AbstractVideoQualityLabel';
+import VideoQualityDialog from './VideoQualityDialog.web';
declare var interfaceConfig: Object;
type Props = AbstractProps & {
/**
- * The message to show within the label.
+ * The redux dispatch function.
*/
- _labelKey: string,
-
- /**
- * Whether to show video quality label or not.
- */
- _showVideoQualityLabel: boolean,
+ dispatch: Function,
/**
* The message to show within the label's tooltip.
*/
_tooltipKey: string,
- /**
- * The redux representation of the JitsiTrack displayed on large video.
- */
- _videoTrack: Object,
-
/**
* Flag controlling visibility of the component.
*/
_visible: boolean,
};
-/**
- * A map of video resolution (number) to translation key.
- *
- * @type {Object}
- */
-const RESOLUTION_TO_TRANSLATION_KEY = {
- '720': 'videoStatus.hd',
- '360': 'videoStatus.sd',
- '180': 'videoStatus.ld'
-};
-
-/**
- * Expected video resolutions placed into an array, sorted from lowest to
- * highest resolution.
- *
- * @type {number[]}
- */
-const RESOLUTIONS
- = Object.keys(RESOLUTION_TO_TRANSLATION_KEY)
- .map(resolution => parseInt(resolution, 10))
- .sort((a, b) => a - b);
-
/**
* React {@code Component} responsible for displaying a label that indicates
* the displayed video state of the current conference. {@code AudioOnlyLabel}
@@ -85,10 +54,8 @@ export class VideoQualityLabel extends AbstractVideoQualityLabel {
render() {
const {
_audioOnly,
- _labelKey,
- _tooltipKey,
- _videoTrack,
_visible,
+ dispatch,
t
} = this.props;
@@ -97,20 +64,17 @@ export class VideoQualityLabel extends AbstractVideoQualityLabel {
return null;
}
- let className, labelContent, tooltipKey;
+ let className, icon, labelContent, onClick, tooltipKey;
if (_audioOnly) {
className = 'audio-only';
labelContent = t('videoStatus.audioOnly');
tooltipKey = 'videoStatus.labelTooltipAudioOnly';
- } else if (!_videoTrack || _videoTrack.muted) {
- className = 'no-video';
- labelContent = t('videoStatus.audioOnly');
- tooltipKey = 'videoStatus.labelTooiltipNoVideo';
} else {
className = 'current-video-quality';
- labelContent = t(_labelKey);
- tooltipKey = _tooltipKey;
+ icon = IconGauge;
+ onClick = () => dispatch(openDialog(VideoQualityDialog));
+ tooltipKey = 'videoStatus.performanceSettings';
}
@@ -120,47 +84,15 @@ export class VideoQualityLabel extends AbstractVideoQualityLabel {
position = { 'bottom' }>
);
}
}
-/**
- * Matches the passed in resolution with a translation keys for describing
- * the resolution. The passed in resolution will be matched with a known
- * resolution that it is at least greater than or equal to.
- *
- * @param {number} resolution - The video height to match with a
- * translation.
- * @private
- * @returns {Object}
- */
-function _mapResolutionToTranslationsKeys(resolution) {
- // Set the default matching resolution of the lowest just in case a match is
- // not found.
- let highestMatchingResolution = RESOLUTIONS[0];
-
- for (let i = 0; i < RESOLUTIONS.length; i++) {
- const knownResolution = RESOLUTIONS[i];
-
- if (resolution >= knownResolution) {
- highestMatchingResolution = knownResolution;
- } else {
- break;
- }
- }
-
- const labelKey
- = RESOLUTION_TO_TRANSLATION_KEY[highestMatchingResolution];
-
- return {
- labelKey,
- tooltipKey: `${labelKey}Tooltip`
- };
-}
-
/**
* Maps (parts of) the Redux state to the associated {@code VideoQualityLabel}'s
* props.
@@ -168,28 +100,13 @@ function _mapResolutionToTranslationsKeys(resolution) {
* @param {Object} state - The Redux state.
* @private
* @returns {{
- * _labelKey: string,
- * _tooltipKey: string,
- * _videoTrack: Object
+ * _audioOnly: boolean,
+ * _visible: boolean
* }}
*/
function _mapStateToProps(state) {
- const { enabled: audioOnly } = state['features/base/audio-only'];
- const { resolution, participantId } = state['features/large-video'];
- const videoTrackOnLargeVideo = getTrackByMediaTypeAndParticipant(
- state['features/base/tracks'],
- MEDIA_TYPE.VIDEO,
- participantId
- );
-
- const translationKeys
- = audioOnly ? {} : _mapResolutionToTranslationsKeys(resolution);
-
return {
..._abstractMapStateToProps(state),
- _labelKey: translationKeys.labelKey,
- _tooltipKey: translationKeys.tooltipKey,
- _videoTrack: videoTrackOnLargeVideo,
_visible: !(shouldDisplayTileView(state) || interfaceConfig.VIDEO_QUALITY_LABEL_DISABLED)
};
}