Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

AudioMuteButton.tsx 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import React, { Component } from 'react';
  2. // We need to reference these files directly to avoid loading things that are not available
  3. // in this environment (e.g. JitsiMeetJS or interfaceConfig)
  4. import { IconMic, IconMicSlash } from '../base/icons/svg';
  5. import { IProps } from '../base/toolbox/components/AbstractButton';
  6. import ToolbarButton from './ToolbarButton';
  7. const { api } = window.alwaysOnTop;
  8. /**
  9. * The type of the React {@code Component} state of {@link AudioMuteButton}.
  10. */
  11. interface IState {
  12. /**
  13. * Whether audio is available is not.
  14. */
  15. audioAvailable: boolean;
  16. /**
  17. * Whether audio is muted or not.
  18. */
  19. audioMuted: boolean;
  20. }
  21. type Props = Partial<IProps>;
  22. /**
  23. * Stateless "mute/unmute audio" button for the Always-on-Top windows.
  24. */
  25. export default class AudioMuteButton extends Component<Props, IState> {
  26. icon = IconMic;
  27. toggledIcon = IconMicSlash;
  28. accessibilityLabel = 'Audio mute';
  29. /**
  30. * Initializes a new {@code AudioMuteButton} instance.
  31. *
  32. * @param {IProps} props - The React {@code Component} props to initialize
  33. * the new {@code AudioMuteButton} instance with.
  34. */
  35. constructor(props: Props) {
  36. super(props);
  37. this.state = {
  38. audioAvailable: false,
  39. audioMuted: true
  40. };
  41. // Bind event handlers so they are only bound once per instance.
  42. this._audioAvailabilityListener
  43. = this._audioAvailabilityListener.bind(this);
  44. this._audioMutedListener = this._audioMutedListener.bind(this);
  45. this._onClick = this._onClick.bind(this);
  46. }
  47. /**
  48. * Sets mouse move listener and initial toolbar timeout.
  49. *
  50. * @inheritdoc
  51. * @returns {void}
  52. */
  53. componentDidMount() {
  54. api.on('audioAvailabilityChanged', this._audioAvailabilityListener);
  55. api.on('audioMuteStatusChanged', this._audioMutedListener);
  56. Promise.all([
  57. api.isAudioAvailable(),
  58. api.isAudioMuted(),
  59. api.isAudioDisabled?.() || Promise.resolve(false)
  60. ])
  61. .then(([ audioAvailable, audioMuted, audioDisabled ]) =>
  62. this.setState({
  63. audioAvailable: audioAvailable && !audioDisabled,
  64. audioMuted
  65. }))
  66. .catch(console.error);
  67. }
  68. /**
  69. * Removes all listeners.
  70. *
  71. * @inheritdoc
  72. * @returns {void}
  73. */
  74. componentWillUnmount() {
  75. api.removeListener(
  76. 'audioAvailabilityChanged',
  77. this._audioAvailabilityListener);
  78. api.removeListener(
  79. 'audioMuteStatusChanged',
  80. this._audioMutedListener);
  81. }
  82. /**
  83. * Handles audio available api events.
  84. *
  85. * @param {{ available: boolean }} status - The new available status.
  86. * @returns {void}
  87. */
  88. _audioAvailabilityListener({ available }: { available: boolean; }) {
  89. this.setState({ audioAvailable: available });
  90. }
  91. /**
  92. * Handles audio muted api events.
  93. *
  94. * @param {{ muted: boolean }} status - The new muted status.
  95. * @returns {void}
  96. */
  97. _audioMutedListener({ muted }: { muted: boolean; }) {
  98. this.setState({ audioMuted: muted });
  99. }
  100. /**
  101. * Indicates if audio is currently muted or not.
  102. *
  103. * @override
  104. * @protected
  105. * @returns {boolean}
  106. */
  107. _isAudioMuted() {
  108. return this.state.audioMuted;
  109. }
  110. /**
  111. * Indicates whether this button is disabled or not.
  112. *
  113. * @override
  114. * @protected
  115. * @returns {boolean}
  116. */
  117. _isDisabled() {
  118. return !this.state.audioAvailable;
  119. }
  120. /**
  121. * Changes the muted state.
  122. *
  123. * @override
  124. * @param {boolean} _audioMuted - Whether audio should be muted or not.
  125. * @protected
  126. * @returns {void}
  127. */
  128. _setAudioMuted(_audioMuted: boolean) {
  129. this.state.audioAvailable && api.executeCommand('toggleAudio');
  130. }
  131. /**
  132. * Handles clicking / pressing the button, and toggles the audio mute state
  133. * accordingly.
  134. *
  135. * @returns {void}
  136. */
  137. _onClick() {
  138. this._setAudioMuted(!this._isAudioMuted());
  139. }
  140. /**
  141. * Implements React's {@link Component#render()}.
  142. *
  143. * @inheritdoc
  144. * @returns {ReactElement}
  145. */
  146. render() {
  147. const toggled = this._isAudioMuted();
  148. return (<ToolbarButton
  149. accessibilityLabel = { this.accessibilityLabel }
  150. disabled = { this._isDisabled() }
  151. icon = { toggled ? this.toggledIcon : this.icon }
  152. onClick = { this._onClick }
  153. toggled = { toggled } />);
  154. }
  155. }