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.

ConferenceInfo.tsx 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* eslint-disable react/no-multi-comp */
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { IReduxState, IStore } from '../../../app/types';
  5. import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
  6. import E2EELabel from '../../../e2ee/components/E2EELabel';
  7. import HighlightButton from '../../../recording/components/Recording/web/HighlightButton';
  8. import RecordingLabel from '../../../recording/components/web/RecordingLabel';
  9. import { showToolbox } from '../../../toolbox/actions.web';
  10. import { isToolboxVisible } from '../../../toolbox/functions.web';
  11. import VideoQualityLabel from '../../../video-quality/components/VideoQualityLabel.web';
  12. import VisitorsCountLabel from '../../../visitors/components/web/VisitorsCountLabel';
  13. import ConferenceTimer from '../ConferenceTimer';
  14. import { getConferenceInfo } from '../functions.web';
  15. import ConferenceInfoContainer from './ConferenceInfoContainer';
  16. import InsecureRoomNameLabel from './InsecureRoomNameLabel';
  17. import RaisedHandsCountLabel from './RaisedHandsCountLabel';
  18. import SpeakerStatsLabel from './SpeakerStatsLabel';
  19. import SubjectText from './SubjectText';
  20. import ToggleTopPanelLabel from './ToggleTopPanelLabel';
  21. /**
  22. * The type of the React {@code Component} props of {@link Subject}.
  23. */
  24. interface IProps {
  25. /**
  26. * The conference info labels to be shown in the conference header.
  27. */
  28. _conferenceInfo: {
  29. alwaysVisible?: string[];
  30. autoHide?: string[];
  31. };
  32. /**
  33. * Indicates whether the component should be visible or not.
  34. */
  35. _visible: boolean;
  36. /**
  37. * Invoked to active other features of the app.
  38. */
  39. dispatch: IStore['dispatch'];
  40. }
  41. const COMPONENTS: Array<{
  42. Component: React.ComponentType<any>;
  43. id: string;
  44. }> = [
  45. {
  46. Component: HighlightButton,
  47. id: 'highlight-moment'
  48. },
  49. {
  50. Component: SubjectText,
  51. id: 'subject'
  52. },
  53. {
  54. Component: ConferenceTimer,
  55. id: 'conference-timer'
  56. },
  57. {
  58. Component: SpeakerStatsLabel,
  59. id: 'participants-count'
  60. },
  61. {
  62. Component: E2EELabel,
  63. id: 'e2ee'
  64. },
  65. {
  66. Component: () => (
  67. <>
  68. <RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
  69. <RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
  70. </>
  71. ),
  72. id: 'recording'
  73. },
  74. {
  75. Component: RaisedHandsCountLabel,
  76. id: 'raised-hands-count'
  77. },
  78. {
  79. Component: VideoQualityLabel,
  80. id: 'video-quality'
  81. },
  82. {
  83. Component: VisitorsCountLabel,
  84. id: 'visitors-count'
  85. },
  86. {
  87. Component: InsecureRoomNameLabel,
  88. id: 'insecure-room'
  89. },
  90. {
  91. Component: ToggleTopPanelLabel,
  92. id: 'top-panel-toggle'
  93. }
  94. ];
  95. /**
  96. * The upper band of the meeing containing the conference name, timer and labels.
  97. *
  98. * @param {Object} props - The props of the component.
  99. * @returns {React$None}
  100. */
  101. class ConferenceInfo extends Component<IProps> {
  102. /**
  103. * Initializes a new {@code ConferenceInfo} instance.
  104. *
  105. * @param {IProps} props - The read-only React {@code Component} props with
  106. * which the new instance is to be initialized.
  107. */
  108. constructor(props: IProps) {
  109. super(props);
  110. this._renderAutoHide = this._renderAutoHide.bind(this);
  111. this._renderAlwaysVisible = this._renderAlwaysVisible.bind(this);
  112. this._onTabIn = this._onTabIn.bind(this);
  113. }
  114. /**
  115. * Callback invoked when the component is focused to show the conference
  116. * info if necessary.
  117. *
  118. * @returns {void}
  119. */
  120. _onTabIn() {
  121. if (this.props._conferenceInfo.autoHide?.length && !this.props._visible) {
  122. this.props.dispatch(showToolbox());
  123. }
  124. }
  125. /**
  126. * Renders auto-hidden info header labels.
  127. *
  128. * @returns {void}
  129. */
  130. _renderAutoHide() {
  131. const { autoHide } = this.props._conferenceInfo;
  132. if (!autoHide?.length) {
  133. return null;
  134. }
  135. return (
  136. <ConferenceInfoContainer
  137. id = 'autoHide'
  138. visible = { this.props._visible }>
  139. {
  140. COMPONENTS
  141. .filter(comp => autoHide.includes(comp.id))
  142. .map(c =>
  143. <c.Component key = { c.id } />
  144. )
  145. }
  146. </ConferenceInfoContainer>
  147. );
  148. }
  149. /**
  150. * Renders the always visible info header labels.
  151. *
  152. * @returns {void}
  153. */
  154. _renderAlwaysVisible() {
  155. const { alwaysVisible } = this.props._conferenceInfo;
  156. if (!alwaysVisible?.length) {
  157. return null;
  158. }
  159. return (
  160. <ConferenceInfoContainer
  161. id = 'alwaysVisible'
  162. visible = { true } >
  163. {
  164. COMPONENTS
  165. .filter(comp => alwaysVisible.includes(comp.id))
  166. .map(c =>
  167. <c.Component key = { c.id } />
  168. )
  169. }
  170. </ConferenceInfoContainer>
  171. );
  172. }
  173. /**
  174. * Implements React's {@link Component#render()}.
  175. *
  176. * @inheritdoc
  177. * @returns {ReactElement}
  178. */
  179. render() {
  180. return (
  181. <div
  182. className = 'details-container'
  183. onFocus = { this._onTabIn }>
  184. { this._renderAlwaysVisible() }
  185. { this._renderAutoHide() }
  186. </div>
  187. );
  188. }
  189. }
  190. /**
  191. * Maps (parts of) the Redux state to the associated
  192. * {@code Subject}'s props.
  193. *
  194. * @param {Object} state - The Redux state.
  195. * @private
  196. * @returns {{
  197. * _visible: boolean,
  198. * _conferenceInfo: Object
  199. * }}
  200. */
  201. function _mapStateToProps(state: IReduxState) {
  202. return {
  203. _visible: isToolboxVisible(state),
  204. _conferenceInfo: getConferenceInfo(state)
  205. };
  206. }
  207. export default connect(_mapStateToProps)(ConferenceInfo);