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

SpeakerStats.tsx 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* eslint-disable lines-around-comment */
  2. import { Theme } from '@mui/material';
  3. import React, { useCallback, useEffect } from 'react';
  4. import { useDispatch, useSelector } from 'react-redux';
  5. import { makeStyles } from 'tss-react/mui';
  6. import { IState } from '../../../app/types';
  7. import Dialog from '../../../base/ui/components/web/Dialog';
  8. import { escapeRegexp } from '../../../base/util/helpers';
  9. // @ts-ignore
  10. import { initSearch, resetSearchCriteria, toggleFaceExpressions } from '../../actions';
  11. import {
  12. DISPLAY_SWITCH_BREAKPOINT,
  13. MOBILE_BREAKPOINT,
  14. RESIZE_SEARCH_SWITCH_CONTAINER_BREAKPOINT
  15. } from '../../constants';
  16. import FaceExpressionsSwitch from './FaceExpressionsSwitch';
  17. import SpeakerStatsLabels from './SpeakerStatsLabels';
  18. import SpeakerStatsList from './SpeakerStatsList';
  19. import SpeakerStatsSearch from './SpeakerStatsSearch';
  20. const useStyles = makeStyles()((theme: Theme) => {
  21. return {
  22. speakerStats: {
  23. '& .row': {
  24. display: 'flex',
  25. alignItems: 'center',
  26. '& .avatar': {
  27. width: '32px',
  28. marginRight: theme.spacing(3)
  29. },
  30. '& .name-time': {
  31. width: 'calc(100% - 48px)',
  32. display: 'flex',
  33. justifyContent: 'space-between',
  34. alignItems: 'center'
  35. },
  36. '& .name-time_expressions-on': {
  37. width: 'calc(47% - 48px)'
  38. },
  39. '& .expressions': {
  40. width: 'calc(53% - 29px)',
  41. display: 'flex',
  42. justifyContent: 'space-between',
  43. '& .expression': {
  44. width: '30px',
  45. textAlign: 'center'
  46. }
  47. }
  48. }
  49. },
  50. labelsContainer: {
  51. position: 'relative'
  52. },
  53. separator: {
  54. position: 'absolute',
  55. width: 'calc(100% + 48px)',
  56. height: 1,
  57. left: -24,
  58. backgroundColor: theme.palette.ui05
  59. },
  60. searchSwitchContainer: {
  61. display: 'flex',
  62. justifyContent: 'space-between',
  63. alignItems: 'center',
  64. width: '100%'
  65. },
  66. searchSwitchContainerExpressionsOn: {
  67. width: '58.5%',
  68. [theme.breakpoints.down(RESIZE_SEARCH_SWITCH_CONTAINER_BREAKPOINT)]: {
  69. width: '100%'
  70. }
  71. },
  72. searchContainer: {
  73. width: '50%'
  74. },
  75. searchContainerFullWidth: {
  76. width: '100%'
  77. }
  78. };
  79. });
  80. const SpeakerStats = () => {
  81. const { faceLandmarks } = useSelector((state: IState) => state['features/base/config']);
  82. const { showFaceExpressions } = useSelector((state: IState) => state['features/speaker-stats']);
  83. const { clientWidth } = useSelector((state: IState) => state['features/base/responsive-ui']);
  84. const displaySwitch = faceLandmarks?.enableDisplayFaceExpressions && clientWidth > DISPLAY_SWITCH_BREAKPOINT;
  85. const displayLabels = clientWidth > MOBILE_BREAKPOINT;
  86. const dispatch = useDispatch();
  87. const { classes } = useStyles();
  88. const onToggleFaceExpressions = useCallback(() =>
  89. dispatch(toggleFaceExpressions())
  90. , [ dispatch ]);
  91. const onSearch = useCallback((criteria = '') => {
  92. dispatch(initSearch(escapeRegexp(criteria)));
  93. }
  94. , [ dispatch ]);
  95. useEffect(() => {
  96. showFaceExpressions && !displaySwitch && dispatch(toggleFaceExpressions());
  97. }, [ clientWidth ]);
  98. useEffect(() => () => dispatch(resetSearchCriteria()), []);
  99. return (
  100. <Dialog
  101. cancel = {{ hidden: true }}
  102. ok = {{ hidden: true }}
  103. size = { showFaceExpressions ? 'large' : 'medium' }
  104. titleKey = 'speakerStats.speakerStats'>
  105. <div className = { classes.speakerStats }>
  106. <div
  107. className = {
  108. `${classes.searchSwitchContainer}
  109. ${showFaceExpressions ? classes.searchSwitchContainerExpressionsOn : ''}`
  110. }>
  111. <div
  112. className = {
  113. displaySwitch
  114. ? classes.searchContainer
  115. : classes.searchContainerFullWidth }>
  116. <SpeakerStatsSearch
  117. onSearch = { onSearch } />
  118. </div>
  119. { displaySwitch
  120. && <FaceExpressionsSwitch
  121. onChange = { onToggleFaceExpressions }
  122. showFaceExpressions = { showFaceExpressions } />
  123. }
  124. </div>
  125. { displayLabels && (
  126. <div className = { classes.labelsContainer }>
  127. <SpeakerStatsLabels
  128. showFaceExpressions = { showFaceExpressions ?? false } />
  129. <div className = { classes.separator } />
  130. </div>
  131. )}
  132. <SpeakerStatsList />
  133. </div>
  134. </Dialog>
  135. );
  136. };
  137. export default SpeakerStats;