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.

MicrophoneButton.tsx 3.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* eslint-disable lines-around-comment */
  2. import React, { useCallback, useState } from 'react';
  3. import { TouchableOpacity, View } from 'react-native';
  4. import { useDispatch, useSelector } from 'react-redux';
  5. import {
  6. ACTION_SHORTCUT_PRESSED as PRESSED,
  7. ACTION_SHORTCUT_RELEASED as RELEASED,
  8. createShortcutEvent
  9. } from '../../../../analytics/AnalyticsEvents';
  10. import { sendAnalytics } from '../../../../analytics/functions';
  11. import { IReduxState } from '../../../../app/types';
  12. import { AUDIO_MUTE_BUTTON_ENABLED } from '../../../../base/flags/constants';
  13. import { getFeatureFlag } from '../../../../base/flags/functions';
  14. import Icon from '../../../../base/icons/components/Icon';
  15. import { IconMicrophone, IconMicrophoneEmptySlash } from '../../../../base/icons/svg';
  16. import { MEDIA_TYPE } from '../../../../base/media/constants';
  17. import { isLocalTrackMuted } from '../../../../base/tracks/functions';
  18. import { isAudioMuteButtonDisabled } from '../../../../toolbox/functions.any';
  19. // @ts-ignore
  20. import { muteLocal } from '../../../../video-menu/actions';
  21. // @ts-ignore
  22. import styles from './styles';
  23. const LONG_PRESS = 'long.press';
  24. /**
  25. * Implements a round audio mute/unmute button of a custom size.
  26. *
  27. * @returns {JSX.Element} - The audio mute round button.
  28. */
  29. const MicrophoneButton = (): JSX.Element | null => {
  30. const dispatch = useDispatch();
  31. const audioMuted = useSelector((state: IReduxState) => isLocalTrackMuted(state['features/base/tracks'],
  32. MEDIA_TYPE.AUDIO));
  33. const disabled = useSelector(isAudioMuteButtonDisabled);
  34. const enabledFlag = useSelector((state: IReduxState) => getFeatureFlag(state, AUDIO_MUTE_BUTTON_ENABLED, true));
  35. const [ longPress, setLongPress ] = useState(false);
  36. if (!enabledFlag) {
  37. return null;
  38. }
  39. const onPressIn = useCallback(() => {
  40. !disabled && dispatch(muteLocal(!audioMuted, MEDIA_TYPE.AUDIO));
  41. }, [ audioMuted, disabled ]);
  42. const onLongPress = useCallback(() => {
  43. if (!disabled && !audioMuted) {
  44. sendAnalytics(createShortcutEvent(
  45. 'push.to.talk',
  46. PRESSED,
  47. {},
  48. LONG_PRESS));
  49. setLongPress(true);
  50. }
  51. }, [ audioMuted, disabled, setLongPress ]);
  52. const onPressOut = useCallback(() => {
  53. if (longPress) {
  54. setLongPress(false);
  55. sendAnalytics(createShortcutEvent(
  56. 'push.to.talk',
  57. RELEASED,
  58. {},
  59. LONG_PRESS
  60. ));
  61. dispatch(muteLocal(true, MEDIA_TYPE.AUDIO));
  62. }
  63. }, [ longPress, setLongPress ]);
  64. return (
  65. <TouchableOpacity
  66. onLongPress = { onLongPress }
  67. onPressIn = { onPressIn }
  68. onPressOut = { onPressOut } >
  69. <View
  70. style = { [
  71. styles.microphoneStyles.container,
  72. !audioMuted && styles.microphoneStyles.unmuted
  73. ] }>
  74. <View
  75. style = { styles.microphoneStyles.iconContainer }>
  76. <Icon
  77. src = { audioMuted ? IconMicrophoneEmptySlash : IconMicrophone }
  78. style = { styles.microphoneStyles.icon } />
  79. </View>
  80. </View>
  81. </TouchableOpacity>
  82. );
  83. };
  84. export default MicrophoneButton;