diff --git a/react/features/toolbox/components/AudioMuteButton.js b/react/features/toolbox/components/AudioMuteButton.js index 5228543ca..9d4b1ad76 100644 --- a/react/features/toolbox/components/AudioMuteButton.js +++ b/react/features/toolbox/components/AudioMuteButton.js @@ -3,7 +3,9 @@ import { connect } from 'react-redux'; import { + ACTION_SHORTCUT_TRIGGERED, AUDIO_MUTE, + createShortcutEvent, createToolbarEvent, sendAnalytics } from '../../analytics'; @@ -13,6 +15,8 @@ import { AbstractAudioMuteButton } from '../../base/toolbox'; import type { AbstractButtonProps } from '../../base/toolbox'; import { isLocalTrackMuted } from '../../base/tracks'; +declare var APP: Object; + /** * The type of the React {@code Component} props of {@link AudioMuteButton}. */ @@ -38,6 +42,45 @@ class AudioMuteButton extends AbstractAudioMuteButton { label = 'toolbar.mute'; tooltip = 'toolbar.mute'; + /** + * Initializes a new {@code AudioMuteButton} instance. + * + * @param {Props} props - The read-only React {@code Component} props with + * which the new instance is to be initialized. + */ + constructor(props: Props) { + super(props); + + // Bind event handlers so they are only bound once per instance. + this._onKeyboardShortcut = this._onKeyboardShortcut.bind(this); + } + + /** + * Registers the keyboard shortcut that toggles the audio muting. + * + * @inheritdoc + * @returns {void} + */ + componentDidMount() { + typeof APP === 'undefined' + || APP.keyboardshortcut.registerShortcut( + 'M', + null, + this._onKeyboardShortcut, + 'keyboardShortcuts.mute'); + } + + /** + * Unregisters the keyboard shortcut that toggles the audio muting. + * + * @inheritdoc + * @returns {void} + */ + componentWillUnmount() { + typeof APP === 'undefined' + || APP.keyboardshortcut.unregisterShortcut('M'); + } + /** * Indicates if audio is currently muted ot nor. * @@ -49,6 +92,25 @@ class AudioMuteButton extends AbstractAudioMuteButton { return this.props._audioMuted; } + _onKeyboardShortcut: () => void; + + /** + * Creates an analytics keyboard shortcut event and dispatches an action to + * toggle the audio muting. + * + * @private + * @returns {void} + */ + _onKeyboardShortcut() { + sendAnalytics( + createShortcutEvent( + AUDIO_MUTE, + ACTION_SHORTCUT_TRIGGERED, + { enable: !this._isAudioMuted() })); + + super._handleClick(); + } + /** * Changes the muted state. * diff --git a/react/features/toolbox/components/VideoMuteButton.js b/react/features/toolbox/components/VideoMuteButton.js index f8bb06217..92f27c34a 100644 --- a/react/features/toolbox/components/VideoMuteButton.js +++ b/react/features/toolbox/components/VideoMuteButton.js @@ -3,7 +3,9 @@ import { connect } from 'react-redux'; import { + ACTION_SHORTCUT_TRIGGERED, VIDEO_MUTE, + createShortcutEvent, createToolbarEvent, sendAnalytics } from '../../analytics'; @@ -17,6 +19,8 @@ import { AbstractVideoMuteButton } from '../../base/toolbox'; import type { AbstractButtonProps } from '../../base/toolbox'; import { isLocalTrackMuted } from '../../base/tracks'; +declare var APP: Object; + /** * The type of the React {@code Component} props of {@link VideoMuteButton}. */ @@ -47,6 +51,45 @@ class VideoMuteButton extends AbstractVideoMuteButton { label = 'toolbar.videomute'; tooltip = 'toolbar.videomute'; + /** + * Initializes a new {@code VideoMuteButton} instance. + * + * @param {Props} props - The read-only React {@code Component} props with + * which the new instance is to be initialized. + */ + constructor(props: Props) { + super(props); + + // Bind event handlers so they are only bound once per instance. + this._onKeyboardShortcut = this._onKeyboardShortcut.bind(this); + } + + /** + * Registers the keyboard shortcut that toggles the video muting. + * + * @inheritdoc + * @returns {void} + */ + componentDidMount() { + typeof APP === 'undefined' + || APP.keyboardshortcut.registerShortcut( + 'V', + null, + this._onKeyboardShortcut, + 'keyboardShortcuts.videoMute'); + } + + /** + * Unregisters the keyboard shortcut that toggles the video muting. + * + * @inheritdoc + * @returns {void} + */ + componentWillUnmount() { + typeof APP === 'undefined' + || APP.keyboardshortcut.unregisterShortcut('V'); + } + /** * Indicates if this button should be disabled or not. * @@ -69,6 +112,25 @@ class VideoMuteButton extends AbstractVideoMuteButton { return this.props._videoMuted; } + _onKeyboardShortcut: () => void; + + /** + * Creates an analytics keyboard shortcut event and dispatches an action to + * toggle the video muting. + * + * @private + * @returns {void} + */ + _onKeyboardShortcut() { + sendAnalytics( + createShortcutEvent( + VIDEO_MUTE, + ACTION_SHORTCUT_TRIGGERED, + { enable: !this._isVideoMuted() })); + + super._handleClick(); + } + /** * Changes the muted state. *