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.

ParticipantItem.js 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // @flow
  2. import React, { type Node } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import { useSelector } from 'react-redux';
  5. import { Avatar } from '../../base/avatar';
  6. import {
  7. Icon,
  8. IconCameraEmpty,
  9. IconCameraEmptyDisabled,
  10. IconMicrophoneEmpty,
  11. IconMicrophoneEmptySlash
  12. } from '../../base/icons';
  13. import { getParticipantDisplayNameWithId } from '../../base/participants';
  14. import { ActionTrigger, MediaState } from '../constants';
  15. import { RaisedHandIndicator } from './RaisedHandIndicator';
  16. import {
  17. ParticipantActionsHover,
  18. ParticipantActionsPermanent,
  19. ParticipantContainer,
  20. ParticipantContent,
  21. ParticipantName,
  22. ParticipantNameContainer,
  23. ParticipantStates
  24. } from './styled';
  25. /**
  26. * Participant actions component mapping depending on trigger type.
  27. */
  28. const Actions = {
  29. [ActionTrigger.Hover]: ParticipantActionsHover,
  30. [ActionTrigger.Permanent]: ParticipantActionsPermanent
  31. };
  32. /**
  33. * Icon mapping for possible participant audio states.
  34. */
  35. const AudioStateIcons = {
  36. [MediaState.ForceMuted]: (
  37. <Icon
  38. size = { 16 }
  39. src = { IconMicrophoneEmptySlash } />
  40. ),
  41. [MediaState.Muted]: (
  42. <Icon
  43. size = { 16 }
  44. src = { IconMicrophoneEmptySlash } />
  45. ),
  46. [MediaState.Unmuted]: (
  47. <Icon
  48. size = { 16 }
  49. src = { IconMicrophoneEmpty } />
  50. ),
  51. [MediaState.None]: null
  52. };
  53. /**
  54. * Icon mapping for possible participant video states.
  55. */
  56. const VideoStateIcons = {
  57. [MediaState.ForceMuted]: (
  58. <Icon
  59. size = { 16 }
  60. src = { IconCameraEmptyDisabled } />
  61. ),
  62. [MediaState.Muted]: (
  63. <Icon
  64. size = { 16 }
  65. src = { IconCameraEmptyDisabled } />
  66. ),
  67. [MediaState.Unmuted]: (
  68. <Icon
  69. size = { 16 }
  70. src = { IconCameraEmpty } />
  71. ),
  72. [MediaState.None]: null
  73. };
  74. type Props = {
  75. /**
  76. * Type of trigger for the participant actions
  77. */
  78. actionsTrigger: ActionTrigger,
  79. /**
  80. * Media state for audio
  81. */
  82. audioMuteState: MediaState,
  83. /**
  84. * React children
  85. */
  86. children: Node,
  87. /**
  88. * Is this item highlighted/raised
  89. */
  90. isHighlighted?: boolean,
  91. /**
  92. * Callback for when the mouse leaves this component
  93. */
  94. onLeave?: Function,
  95. /**
  96. * Participant reference
  97. */
  98. participant: Object,
  99. /**
  100. * Media state for video
  101. */
  102. videoMuteState: MediaState
  103. }
  104. export const ParticipantItem = ({
  105. children,
  106. isHighlighted,
  107. onLeave,
  108. actionsTrigger = ActionTrigger.Hover,
  109. audioMuteState = MediaState.None,
  110. videoMuteState = MediaState.None,
  111. participant: p
  112. }: Props) => {
  113. const ParticipantActions = Actions[actionsTrigger];
  114. const { t } = useTranslation();
  115. const name = useSelector(getParticipantDisplayNameWithId(p.id));
  116. return (
  117. <ParticipantContainer
  118. isHighlighted = { isHighlighted }
  119. onMouseLeave = { onLeave }
  120. trigger = { actionsTrigger }>
  121. <Avatar
  122. className = 'participant-avatar'
  123. participantId = { p.id }
  124. size = { 32 } />
  125. <ParticipantContent>
  126. <ParticipantNameContainer>
  127. <ParticipantName>
  128. { name }
  129. </ParticipantName>
  130. { p.local ? <span>&nbsp;({t('chat.you')})</span> : null }
  131. </ParticipantNameContainer>
  132. { !p.local && <ParticipantActions children = { children } /> }
  133. <ParticipantStates>
  134. {p.raisedHand && <RaisedHandIndicator />}
  135. {VideoStateIcons[videoMuteState]}
  136. {AudioStateIcons[audioMuteState]}
  137. </ParticipantStates>
  138. </ParticipantContent>
  139. </ParticipantContainer>
  140. );
  141. };