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.

AbstractSpeakerStatsList.js 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // @flow
  2. import { useCallback, useEffect, useRef } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import { useDispatch, useSelector } from 'react-redux';
  5. import { getLocalParticipant } from '../../base/participants';
  6. import { initUpdateStats } from '../actions.any';
  7. import {
  8. SPEAKER_STATS_RELOAD_INTERVAL
  9. } from '../constants';
  10. /**
  11. * Component that renders the list of speaker stats.
  12. *
  13. * @param {Function} speakerStatsItem - React element tu use when rendering.
  14. * @param {Object} itemStyles - Styles for the speaker stats item.
  15. * @returns {Function}
  16. */
  17. const abstractSpeakerStatsList = (speakerStatsItem: Function, itemStyles?: Object): Function[] => {
  18. const dispatch = useDispatch();
  19. const { t } = useTranslation();
  20. const conference = useSelector(state => state['features/base/conference'].conference);
  21. const {
  22. stats: speakerStats,
  23. showFaceExpressions,
  24. sortedSpeakerStatsIds
  25. } = useSelector(state => state['features/speaker-stats']);
  26. const localParticipant = useSelector(getLocalParticipant);
  27. const { defaultRemoteDisplayName } = useSelector(
  28. state => state['features/base/config']) || {};
  29. const { faceLandmarks } = useSelector(state => state['features/base/config']) || {};
  30. const { faceExpressions } = useSelector(state => state['features/face-landmarks']) || {};
  31. const reloadInterval = useRef(null);
  32. /**
  33. * Update the internal state with the latest speaker stats.
  34. *
  35. * @returns {Object}
  36. * @private
  37. */
  38. const getSpeakerStats = useCallback(() => {
  39. const stats = conference.getSpeakerStats();
  40. for (const userId in stats) {
  41. if (stats[userId]) {
  42. if (stats[userId].isLocalStats()) {
  43. const meString = t('me');
  44. stats[userId].setDisplayName(
  45. localParticipant.name
  46. ? `${localParticipant.name} (${meString})`
  47. : meString
  48. );
  49. if (faceLandmarks?.enableDisplayFaceExpressions) {
  50. stats[userId].setFaceExpressions(faceExpressions);
  51. }
  52. }
  53. if (!stats[userId].getDisplayName()) {
  54. stats[userId].setDisplayName(
  55. conference.getParticipantById(userId)?.name
  56. );
  57. }
  58. }
  59. }
  60. return stats;
  61. }, [ faceExpressions ]);
  62. const updateStats = useCallback(
  63. () => dispatch(initUpdateStats(getSpeakerStats)),
  64. [ dispatch, initUpdateStats, getSpeakerStats ]);
  65. useEffect(() => {
  66. if (reloadInterval.current) {
  67. clearInterval(reloadInterval.current);
  68. }
  69. reloadInterval.current = setInterval(() => {
  70. updateStats();
  71. }, SPEAKER_STATS_RELOAD_INTERVAL);
  72. return () => clearInterval(reloadInterval.current);
  73. }, [ faceExpressions ]);
  74. const localSpeakerStats = Object.keys(speakerStats).length === 0 ? getSpeakerStats() : speakerStats;
  75. const localSortedSpeakerStatsIds
  76. = sortedSpeakerStatsIds.length === 0 ? Object.keys(localSpeakerStats) : sortedSpeakerStatsIds;
  77. const userIds = localSortedSpeakerStatsIds.filter(id => localSpeakerStats[id] && !localSpeakerStats[id].hidden);
  78. return userIds.map(userId => {
  79. const statsModel = localSpeakerStats[userId];
  80. const props = {};
  81. props.isDominantSpeaker = statsModel.isDominantSpeaker();
  82. props.dominantSpeakerTime = statsModel.getTotalDominantSpeakerTime();
  83. props.participantId = userId;
  84. props.hasLeft = statsModel.hasLeft();
  85. if (showFaceExpressions) {
  86. props.faceExpressions = statsModel.getFaceExpressions();
  87. }
  88. props.hidden = statsModel.hidden;
  89. props.showFaceExpressions = showFaceExpressions;
  90. props.displayName = statsModel.getDisplayName() || defaultRemoteDisplayName;
  91. if (itemStyles) {
  92. props.styles = itemStyles;
  93. }
  94. props.t = t;
  95. return speakerStatsItem(props);
  96. });
  97. };
  98. export default abstractSpeakerStatsList;