You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VideoQualityLabel.web.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // @flow
  2. import React from 'react';
  3. import { translate } from '../../base/i18n';
  4. import { Label } from '../../base/label';
  5. import { MEDIA_TYPE } from '../../base/media';
  6. import { connect } from '../../base/redux';
  7. import { Tooltip } from '../../base/tooltip';
  8. import { getTrackByMediaTypeAndParticipant } from '../../base/tracks';
  9. import { shouldDisplayTileView } from '../../video-layout';
  10. import AbstractVideoQualityLabel, {
  11. _abstractMapStateToProps,
  12. type Props as AbstractProps
  13. } from './AbstractVideoQualityLabel';
  14. declare var interfaceConfig: Object;
  15. type Props = AbstractProps & {
  16. /**
  17. * The message to show within the label.
  18. */
  19. _labelKey: string,
  20. /**
  21. * Whether to show video quality label or not.
  22. */
  23. _showVideoQualityLabel: boolean,
  24. /**
  25. * The message to show within the label's tooltip.
  26. */
  27. _tooltipKey: string,
  28. /**
  29. * The redux representation of the JitsiTrack displayed on large video.
  30. */
  31. _videoTrack: Object,
  32. /**
  33. * Flag controlling visibility of the component.
  34. */
  35. _visible: boolean,
  36. };
  37. /**
  38. * A map of video resolution (number) to translation key.
  39. *
  40. * @type {Object}
  41. */
  42. const RESOLUTION_TO_TRANSLATION_KEY = {
  43. '720': 'videoStatus.hd',
  44. '360': 'videoStatus.sd',
  45. '180': 'videoStatus.ld'
  46. };
  47. /**
  48. * Expected video resolutions placed into an array, sorted from lowest to
  49. * highest resolution.
  50. *
  51. * @type {number[]}
  52. */
  53. const RESOLUTIONS
  54. = Object.keys(RESOLUTION_TO_TRANSLATION_KEY)
  55. .map(resolution => parseInt(resolution, 10))
  56. .sort((a, b) => a - b);
  57. /**
  58. * React {@code Component} responsible for displaying a label that indicates
  59. * the displayed video state of the current conference. {@code AudioOnlyLabel}
  60. * will display when the conference is in audio only mode. {@code HDVideoLabel}
  61. * will display if not in audio only mode and a high-definition large video is
  62. * being displayed.
  63. */
  64. export class VideoQualityLabel extends AbstractVideoQualityLabel<Props> {
  65. /**
  66. * Implements React's {@link Component#render()}.
  67. *
  68. * @inheritdoc
  69. * @returns {ReactElement}
  70. */
  71. render() {
  72. const {
  73. _audioOnly,
  74. _labelKey,
  75. _tooltipKey,
  76. _videoTrack,
  77. _visible,
  78. t
  79. } = this.props;
  80. if (!_visible) {
  81. return null;
  82. }
  83. let className, labelContent, tooltipKey;
  84. if (_audioOnly) {
  85. className = 'audio-only';
  86. labelContent = t('videoStatus.audioOnly');
  87. tooltipKey = 'videoStatus.labelTooltipAudioOnly';
  88. } else if (!_videoTrack || _videoTrack.muted) {
  89. className = 'no-video';
  90. labelContent = t('videoStatus.audioOnly');
  91. tooltipKey = 'videoStatus.labelTooiltipNoVideo';
  92. } else {
  93. className = 'current-video-quality';
  94. labelContent = t(_labelKey);
  95. tooltipKey = _tooltipKey;
  96. }
  97. return (
  98. <Tooltip
  99. content = { t(tooltipKey) }
  100. position = { 'bottom' }>
  101. <Label
  102. className = { className }
  103. id = 'videoResolutionLabel'
  104. text = { labelContent } />
  105. </Tooltip>
  106. );
  107. }
  108. }
  109. /**
  110. * Matches the passed in resolution with a translation keys for describing
  111. * the resolution. The passed in resolution will be matched with a known
  112. * resolution that it is at least greater than or equal to.
  113. *
  114. * @param {number} resolution - The video height to match with a
  115. * translation.
  116. * @private
  117. * @returns {Object}
  118. */
  119. function _mapResolutionToTranslationsKeys(resolution) {
  120. // Set the default matching resolution of the lowest just in case a match is
  121. // not found.
  122. let highestMatchingResolution = RESOLUTIONS[0];
  123. for (let i = 0; i < RESOLUTIONS.length; i++) {
  124. const knownResolution = RESOLUTIONS[i];
  125. if (resolution >= knownResolution) {
  126. highestMatchingResolution = knownResolution;
  127. } else {
  128. break;
  129. }
  130. }
  131. const labelKey
  132. = RESOLUTION_TO_TRANSLATION_KEY[highestMatchingResolution];
  133. return {
  134. labelKey,
  135. tooltipKey: `${labelKey}Tooltip`
  136. };
  137. }
  138. /**
  139. * Maps (parts of) the Redux state to the associated {@code VideoQualityLabel}'s
  140. * props.
  141. *
  142. * @param {Object} state - The Redux state.
  143. * @private
  144. * @returns {{
  145. * _labelKey: string,
  146. * _tooltipKey: string,
  147. * _videoTrack: Object
  148. * }}
  149. */
  150. function _mapStateToProps(state) {
  151. const { enabled: audioOnly } = state['features/base/audio-only'];
  152. const { resolution, participantId } = state['features/large-video'];
  153. const videoTrackOnLargeVideo = getTrackByMediaTypeAndParticipant(
  154. state['features/base/tracks'],
  155. MEDIA_TYPE.VIDEO,
  156. participantId
  157. );
  158. const translationKeys
  159. = audioOnly ? {} : _mapResolutionToTranslationsKeys(resolution);
  160. return {
  161. ..._abstractMapStateToProps(state),
  162. _labelKey: translationKeys.labelKey,
  163. _tooltipKey: translationKeys.tooltipKey,
  164. _videoTrack: videoTrackOnLargeVideo,
  165. _visible: !(shouldDisplayTileView(state) || interfaceConfig.VIDEO_QUALITY_LABEL_DISABLED)
  166. };
  167. }
  168. export default translate(connect(_mapStateToProps)(VideoQualityLabel));