Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

functions.js 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // @flow
  2. import _ from 'lodash';
  3. import { getParticipantById, PARTICIPANT_ROLE } from '../base/participants';
  4. import { objectSort } from '../base/util';
  5. /**
  6. * Checks if the speaker stats search is disabled.
  7. *
  8. * @param {*} state - The redux state.
  9. * @returns {boolean} - True if the speaker stats search is disabled and false otherwise.
  10. */
  11. export function isSpeakerStatsSearchDisabled(state: Object) {
  12. return state['features/base/config']?.disableSpeakerStatsSearch;
  13. }
  14. /**
  15. * Gets whether participants in speaker stats should be ordered or not, and with what priority.
  16. *
  17. * @param {*} state - The redux state.
  18. * @returns {Array<string>} - The speaker stats order array or an empty array.
  19. */
  20. export function getSpeakerStatsOrder(state: Object) {
  21. return state['features/base/config']?.speakerStatsOrder ?? [
  22. 'role',
  23. 'name',
  24. 'hasLeft'
  25. ];
  26. }
  27. /**
  28. * Gets speaker stats.
  29. *
  30. * @param {*} state - The redux state.
  31. * @returns {Object} - The speaker stats.
  32. */
  33. export function getSpeakerStats(state: Object) {
  34. return state['features/speaker-stats']?.stats ?? {};
  35. }
  36. /**
  37. * Gets speaker stats search criteria.
  38. *
  39. * @param {*} state - The redux state.
  40. * @returns {string | null} - The search criteria.
  41. */
  42. export function getSearchCriteria(state: Object) {
  43. return state['features/speaker-stats']?.criteria;
  44. }
  45. /**
  46. * Gets if speaker stats reorder is pending.
  47. *
  48. * @param {*} state - The redux state.
  49. * @returns {boolean} - The pending reorder flag.
  50. */
  51. export function getPendingReorder(state: Object) {
  52. return state['features/speaker-stats']?.pendingReorder ?? false;
  53. }
  54. /**
  55. * Get sorted speaker stats based on a configuration setting.
  56. *
  57. * @param {Object} state - The redux state.
  58. * @param {Object} stats - The current speaker stats.
  59. * @returns {Object} - Ordered speaker stats.
  60. * @public
  61. */
  62. export function getSortedSpeakerStats(state: Object, stats: Object) {
  63. const orderConfig = getSpeakerStatsOrder(state);
  64. if (orderConfig) {
  65. const enhancedStats = getEnhancedStatsForOrdering(state, stats, orderConfig);
  66. const sortedStats = objectSort(enhancedStats, (currentParticipant, nextParticipant) => {
  67. if (orderConfig.includes('hasLeft')) {
  68. if (nextParticipant.hasLeft() && !currentParticipant.hasLeft()) {
  69. return -1;
  70. } else if (currentParticipant.hasLeft() && !nextParticipant.hasLeft()) {
  71. return 1;
  72. }
  73. }
  74. let result;
  75. for (const sortCriteria of orderConfig) {
  76. switch (sortCriteria) {
  77. case 'role':
  78. if (!nextParticipant.isModerator && currentParticipant.isModerator) {
  79. result = -1;
  80. } else if (!currentParticipant.isModerator && nextParticipant.isModerator) {
  81. result = 1;
  82. } else {
  83. result = 0;
  84. }
  85. break;
  86. case 'name':
  87. result = (currentParticipant.displayName || '').localeCompare(
  88. nextParticipant.displayName || ''
  89. );
  90. break;
  91. }
  92. if (result !== 0) {
  93. break;
  94. }
  95. }
  96. return result;
  97. });
  98. return sortedStats;
  99. }
  100. }
  101. /**
  102. * Enhance speaker stats to include data needed for ordering.
  103. *
  104. * @param {Object} state - The redux state.
  105. * @param {Object} stats - Speaker stats.
  106. * @param {Array<string>} orderConfig - Ordering configuration.
  107. * @returns {Object} - Enhanced speaker stats.
  108. * @public
  109. */
  110. function getEnhancedStatsForOrdering(state, stats, orderConfig) {
  111. if (!orderConfig) {
  112. return stats;
  113. }
  114. for (const id in stats) {
  115. if (stats[id].hasOwnProperty('_hasLeft') && !stats[id].hasLeft()) {
  116. if (orderConfig.includes('role')) {
  117. const participant = getParticipantById(state, stats[id].getUserId());
  118. stats[id].isModerator = participant && participant.role === PARTICIPANT_ROLE.MODERATOR;
  119. }
  120. }
  121. }
  122. return stats;
  123. }
  124. /**
  125. * Filter stats by search criteria.
  126. *
  127. * @param {Object} state - The redux state.
  128. * @param {Object | undefined} stats - The unfiltered stats.
  129. *
  130. * @returns {Object} - Filtered speaker stats.
  131. * @public
  132. */
  133. export function filterBySearchCriteria(state: Object, stats: ?Object) {
  134. const filteredStats = _.cloneDeep(stats ?? getSpeakerStats(state));
  135. const criteria = getSearchCriteria(state);
  136. if (criteria !== null) {
  137. const searchRegex = new RegExp(criteria, 'gi');
  138. for (const id in filteredStats) {
  139. if (filteredStats[id].hasOwnProperty('_isLocalStats')) {
  140. const name = filteredStats[id].getDisplayName();
  141. filteredStats[id].hidden = !name || !name.match(searchRegex);
  142. }
  143. }
  144. }
  145. return filteredStats;
  146. }