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.2KB

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