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.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* @flow */
  2. import React from 'react';
  3. import { getConferenceName } from '../../../base/conference/functions';
  4. import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
  5. import { getParticipantCount } from '../../../base/participants/functions';
  6. import { connect } from '../../../base/redux';
  7. import { E2EELabel } from '../../../e2ee';
  8. import { LocalRecordingLabel } from '../../../local-recording';
  9. import { getSessionStatusToShow, RecordingLabel } from '../../../recording';
  10. import { isToolboxVisible } from '../../../toolbox/functions.web';
  11. import { TranscribingLabel } from '../../../transcribing';
  12. import { VideoQualityLabel } from '../../../video-quality';
  13. import ConferenceTimer from '../ConferenceTimer';
  14. import ParticipantsCount from './ParticipantsCount';
  15. import { InsecureRoomNameLabel } from '.';
  16. /**
  17. * The type of the React {@code Component} props of {@link Subject}.
  18. */
  19. type Props = {
  20. /**
  21. * Whether the info should span across the full width.
  22. */
  23. _fullWidth: boolean,
  24. /**
  25. * Whether the conference name and timer should be displayed or not.
  26. */
  27. _hideConferenceNameAndTimer: boolean,
  28. /**
  29. * Whether the conference timer should be shown or not.
  30. */
  31. _hideConferenceTimer: boolean,
  32. /**
  33. * Whether the recording label should be shown or not.
  34. */
  35. _hideRecordingLabel: boolean,
  36. /**
  37. * Whether the participant count should be shown or not.
  38. */
  39. _showParticipantCount: boolean,
  40. /**
  41. * The subject or the of the conference.
  42. * Falls back to conference name.
  43. */
  44. _subject: string,
  45. /**
  46. * Indicates whether the component should be visible or not.
  47. */
  48. _visible: boolean,
  49. /**
  50. * Whether or not the recording label is visible.
  51. */
  52. _recordingLabel: boolean
  53. };
  54. const getLeftMargin = () => {
  55. const subjectContainerWidth = document.getElementById('subject-container')?.clientWidth ?? 0;
  56. const recContainerWidth = document.getElementById('rec-container')?.clientWidth ?? 0;
  57. const subjectDetailsContainer = document.getElementById('subject-details-container')?.clientWidth ?? 0;
  58. return (subjectContainerWidth - recContainerWidth - subjectDetailsContainer) / 2;
  59. };
  60. /**
  61. * The upper band of the meeing containing the conference name, timer and labels.
  62. *
  63. * @param {Object} props - The props of the component.
  64. * @returns {React$None}
  65. */
  66. function ConferenceInfo(props: Props) {
  67. const {
  68. _hideConferenceNameAndTimer,
  69. _hideConferenceTimer,
  70. _showParticipantCount,
  71. _hideRecordingLabel,
  72. _subject,
  73. _fullWidth,
  74. _visible,
  75. _recordingLabel
  76. } = props;
  77. return (
  78. <div className = { `subject ${_recordingLabel ? 'recording' : ''} ${_visible ? 'visible' : ''}` }>
  79. <div
  80. className = { `subject-info-container${_fullWidth ? ' subject-info-container--full-width' : ''}` }
  81. id = 'subject-container'>
  82. {!_hideRecordingLabel && <div
  83. className = 'show-always'
  84. id = 'rec-container'
  85. // eslint-disable-next-line react-native/no-inline-styles
  86. style = {{
  87. marginLeft: !_recordingLabel || _visible ? 0 : getLeftMargin()
  88. }}>
  89. <RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
  90. <RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
  91. <LocalRecordingLabel />
  92. </div>
  93. }
  94. <div
  95. className = 'subject-details-container'
  96. id = 'subject-details-container'>
  97. {
  98. !_hideConferenceNameAndTimer
  99. && <div className = 'subject-info'>
  100. { _subject && <span className = 'subject-text'>{ _subject }</span>}
  101. { !_hideConferenceTimer && <ConferenceTimer /> }
  102. </div>
  103. }
  104. { _showParticipantCount && <ParticipantsCount /> }
  105. <E2EELabel />
  106. {_hideRecordingLabel && (
  107. <>
  108. <RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
  109. <RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
  110. <LocalRecordingLabel />
  111. </>
  112. )}
  113. <TranscribingLabel />
  114. <VideoQualityLabel />
  115. <InsecureRoomNameLabel />
  116. </div>
  117. </div>
  118. </div>
  119. );
  120. }
  121. /**
  122. * Maps (parts of) the Redux state to the associated
  123. * {@code Subject}'s props.
  124. *
  125. * @param {Object} state - The Redux state.
  126. * @private
  127. * @returns {{
  128. * _hideConferenceTimer: boolean,
  129. * _showParticipantCount: boolean,
  130. * _subject: string,
  131. * _visible: boolean
  132. * }}
  133. */
  134. function _mapStateToProps(state) {
  135. const participantCount = getParticipantCount(state);
  136. const {
  137. hideConferenceTimer,
  138. hideConferenceSubject,
  139. hideParticipantsStats,
  140. hideRecordingLabel,
  141. iAmRecorder
  142. } = state['features/base/config'];
  143. const { clientWidth } = state['features/base/responsive-ui'];
  144. const shouldHideRecordingLabel = hideRecordingLabel || iAmRecorder;
  145. const fileRecordingStatus = getSessionStatusToShow(state, JitsiRecordingConstants.mode.FILE);
  146. const streamRecordingStatus = getSessionStatusToShow(state, JitsiRecordingConstants.mode.STREAM);
  147. const isFileRecording = fileRecordingStatus ? fileRecordingStatus !== JitsiRecordingConstants.status.OFF : false;
  148. const isStreamRecording = streamRecordingStatus
  149. ? streamRecordingStatus !== JitsiRecordingConstants.status.OFF : false;
  150. const { isEngaged } = state['features/local-recording'];
  151. return {
  152. _hideConferenceNameAndTimer: clientWidth < 300,
  153. _hideConferenceTimer: Boolean(hideConferenceTimer),
  154. _hideRecordingLabel: shouldHideRecordingLabel,
  155. _fullWidth: state['features/video-layout'].tileViewEnabled,
  156. _showParticipantCount: participantCount > 2 && !hideParticipantsStats,
  157. _subject: hideConferenceSubject ? '' : getConferenceName(state),
  158. _visible: isToolboxVisible(state),
  159. _recordingLabel: (isFileRecording || isStreamRecording || isEngaged) && !shouldHideRecordingLabel
  160. };
  161. }
  162. export default connect(_mapStateToProps)(ConferenceInfo);