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.

SpeakerStats.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // @flow
  2. import { makeStyles } from '@material-ui/core/styles';
  3. import React, { useCallback, useEffect } from 'react';
  4. import { useSelector, useDispatch } from 'react-redux';
  5. import { Dialog } from '../../../base/dialog';
  6. import { escapeRegexp } from '../../../base/util';
  7. import { resetSearchCriteria, toggleFaceExpressions, initSearch } from '../../actions';
  8. import {
  9. DISPLAY_SWITCH_BREAKPOINT,
  10. MOBILE_BREAKPOINT,
  11. RESIZE_SEARCH_SWITCH_CONTAINER_BREAKPOINT
  12. } from '../../constants';
  13. import FaceExpressionsSwitch from './FaceExpressionsSwitch';
  14. import SpeakerStatsLabels from './SpeakerStatsLabels';
  15. import SpeakerStatsList from './SpeakerStatsList';
  16. import SpeakerStatsSearch from './SpeakerStatsSearch';
  17. const useStyles = makeStyles(theme => {
  18. return {
  19. speakerStats: {
  20. '& .row': {
  21. display: 'flex',
  22. alignItems: 'center',
  23. '& .avatar': {
  24. width: '32px',
  25. marginRight: theme.spacing(3)
  26. },
  27. '& .name-time': {
  28. width: 'calc(100% - 48px)',
  29. display: 'flex',
  30. justifyContent: 'space-between',
  31. alignItems: 'center'
  32. },
  33. '& .name-time_expressions-on': {
  34. width: 'calc(47% - 48px)'
  35. },
  36. '& .expressions': {
  37. width: 'calc(53% - 29px)',
  38. display: 'flex',
  39. justifyContent: 'space-between',
  40. '& .expression': {
  41. width: '30px',
  42. textAlign: 'center'
  43. }
  44. }
  45. }
  46. },
  47. footer: {
  48. display: 'none !important'
  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 => state['features/base/config']);
  82. const { showFaceExpressions } = useSelector(state => state['features/speaker-stats']);
  83. const { clientWidth } = useSelector(state => 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. cancelKey = 'dialog.close'
  102. classes = {{ footer: classes.footer }}
  103. hideCancelButton = { true }
  104. submitDisabled = { true }
  105. titleKey = 'speakerStats.speakerStats'
  106. width = { showFaceExpressions ? '664px' : 'small' }>
  107. <div className = { classes.speakerStats }>
  108. <div
  109. className = {
  110. `${classes.searchSwitchContainer}
  111. ${showFaceExpressions ? classes.searchSwitchContainerExpressionsOn : ''}`
  112. }>
  113. <div
  114. className = {
  115. displaySwitch
  116. ? classes.searchContainer
  117. : classes.searchContainerFullWidth }>
  118. <SpeakerStatsSearch
  119. onSearch = { onSearch } />
  120. </div>
  121. { displaySwitch
  122. && <FaceExpressionsSwitch
  123. onChange = { onToggleFaceExpressions }
  124. showFaceExpressions = { showFaceExpressions } />
  125. }
  126. </div>
  127. { displayLabels && (
  128. <div className = { classes.labelsContainer }>
  129. <SpeakerStatsLabels
  130. showFaceExpressions = { showFaceExpressions ?? false } />
  131. <div className = { classes.separator } />
  132. </div>
  133. )}
  134. <SpeakerStatsList />
  135. </div>
  136. </Dialog>
  137. );
  138. };
  139. export default SpeakerStats;