mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-02-08 23:10:20 +00:00
311 lines
11 KiB
TypeScript
311 lines
11 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { batch, useDispatch, useSelector } from 'react-redux';
|
|
|
|
import { ACTION_SHORTCUT_TRIGGERED, createShortcutEvent } from '../analytics/AnalyticsEvents';
|
|
import { sendAnalytics } from '../analytics/functions';
|
|
import { IReduxState } from '../app/types';
|
|
import { getToolbarButtons, isToolbarButtonEnabled } from '../base/config/functions.web';
|
|
import { toggleDialog } from '../base/dialog/actions';
|
|
import JitsiMeetJS from '../base/lib-jitsi-meet';
|
|
import { raiseHand } from '../base/participants/actions';
|
|
import { getLocalParticipant, hasRaisedHand } from '../base/participants/functions';
|
|
import { toggleChat } from '../chat/actions.web';
|
|
import { setGifMenuVisibility } from '../gifs/actions';
|
|
import { isGifEnabled } from '../gifs/function.any';
|
|
import { registerShortcut, unregisterShortcut } from '../keyboard-shortcuts/actions.any';
|
|
import {
|
|
close as closeParticipantsPane,
|
|
open as openParticipantsPane
|
|
} from '../participants-pane/actions.web';
|
|
import { getParticipantsPaneOpen } from '../participants-pane/functions';
|
|
import { addReactionToBuffer } from '../reactions/actions.any';
|
|
import { toggleReactionsMenuVisibility } from '../reactions/actions.web';
|
|
import { REACTIONS } from '../reactions/constants';
|
|
import { isReactionsEnabled } from '../reactions/functions.any';
|
|
import { startScreenShareFlow } from '../screen-share/actions.web';
|
|
import { isScreenVideoShared } from '../screen-share/functions';
|
|
import SpeakerStats from '../speaker-stats/components/web/SpeakerStats';
|
|
import { isSpeakerStatsDisabled } from '../speaker-stats/functions';
|
|
import { toggleTileView } from '../video-layout/actions.any';
|
|
import { shouldDisplayTileView } from '../video-layout/functions.any';
|
|
import VideoQualityDialog from '../video-quality/components/VideoQualityDialog.web';
|
|
|
|
import { setFullScreen } from './actions.web';
|
|
import { isDesktopShareButtonDisabled } from './functions.web';
|
|
|
|
export const useKeyboardShortcuts = (toolbarButtons: Array<string>) => {
|
|
const dispatch = useDispatch();
|
|
const _isSpeakerStatsDisabled = useSelector(isSpeakerStatsDisabled);
|
|
const _toolbarButtons = useSelector((state: IReduxState) => toolbarButtons || getToolbarButtons(state));
|
|
const chatOpen = useSelector((state: IReduxState) => state['features/chat'].isOpen);
|
|
const desktopSharingButtonDisabled = useSelector(isDesktopShareButtonDisabled);
|
|
const desktopSharingEnabled = JitsiMeetJS.isDesktopSharingEnabled();
|
|
const fullScreen = useSelector((state: IReduxState) => state['features/toolbox'].fullScreen);
|
|
const gifsEnabled = useSelector(isGifEnabled);
|
|
const localParticipant = useSelector(getLocalParticipant);
|
|
const participantsPaneOpen = useSelector(getParticipantsPaneOpen);
|
|
const raisedHand = hasRaisedHand(localParticipant);
|
|
const reactionsEnabled = useSelector(isReactionsEnabled);
|
|
const screenSharing = useSelector(isScreenVideoShared);
|
|
const tileViewEnabled = useSelector(shouldDisplayTileView);
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling the display of chat.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleChat() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.chat',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{
|
|
enable: !chatOpen
|
|
}));
|
|
|
|
// Checks if there was any text selected by the user.
|
|
// Used for when we press simultaneously keys for copying
|
|
// text messages from the chat board
|
|
if (window.getSelection()?.toString() !== '') {
|
|
return false;
|
|
}
|
|
|
|
dispatch(toggleChat());
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling the display of the participants pane.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleParticipantsPane() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.participants-pane',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{
|
|
enable: !participantsPaneOpen
|
|
}));
|
|
|
|
if (participantsPaneOpen) {
|
|
dispatch(closeParticipantsPane());
|
|
} else {
|
|
dispatch(openParticipantsPane());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling the display of Video Quality.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleVideoQuality() {
|
|
sendAnalytics(createShortcutEvent('video.quality'));
|
|
|
|
dispatch(toggleDialog(VideoQualityDialog));
|
|
}
|
|
|
|
/**
|
|
* Dispatches an action for toggling the tile view.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleTileView() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.tileview',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{
|
|
enable: !tileViewEnabled
|
|
}));
|
|
|
|
dispatch(toggleTileView());
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling full screen mode.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleFullScreen() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.fullscreen',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{
|
|
enable: !fullScreen
|
|
}));
|
|
dispatch(setFullScreen(!fullScreen));
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling raise hand.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleRaiseHand() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.raise.hand',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{ enable: !raisedHand }));
|
|
|
|
dispatch(raiseHand(!raisedHand));
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling screensharing.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onToggleScreenshare() {
|
|
// Ignore the shortcut if the button is disabled.
|
|
if (desktopSharingButtonDisabled) {
|
|
return;
|
|
}
|
|
sendAnalytics(createShortcutEvent(
|
|
'toggle.screen.sharing',
|
|
ACTION_SHORTCUT_TRIGGERED,
|
|
{
|
|
enable: !screenSharing
|
|
}));
|
|
|
|
if (desktopSharingEnabled && !desktopSharingButtonDisabled) {
|
|
dispatch(startScreenShareFlow(!screenSharing));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates an analytics keyboard shortcut event and dispatches an action for
|
|
* toggling speaker stats.
|
|
*
|
|
* @private
|
|
* @returns {void}
|
|
*/
|
|
function onSpeakerStats() {
|
|
sendAnalytics(createShortcutEvent(
|
|
'speaker.stats'
|
|
));
|
|
|
|
dispatch(toggleDialog(SpeakerStats, {
|
|
conference: APP.conference
|
|
}));
|
|
}
|
|
|
|
useEffect(() => {
|
|
const KEYBOARD_SHORTCUTS = [
|
|
isToolbarButtonEnabled('videoquality', _toolbarButtons) && {
|
|
character: 'A',
|
|
exec: onToggleVideoQuality,
|
|
helpDescription: 'toolbar.callQuality'
|
|
},
|
|
isToolbarButtonEnabled('chat', _toolbarButtons) && {
|
|
character: 'C',
|
|
exec: onToggleChat,
|
|
helpDescription: 'keyboardShortcuts.toggleChat'
|
|
},
|
|
isToolbarButtonEnabled('desktop', _toolbarButtons) && {
|
|
character: 'D',
|
|
exec: onToggleScreenshare,
|
|
helpDescription: 'keyboardShortcuts.toggleScreensharing'
|
|
},
|
|
isToolbarButtonEnabled('participants-pane', _toolbarButtons) && {
|
|
character: 'P',
|
|
exec: onToggleParticipantsPane,
|
|
helpDescription: 'keyboardShortcuts.toggleParticipantsPane'
|
|
},
|
|
isToolbarButtonEnabled('raisehand', _toolbarButtons) && {
|
|
character: 'R',
|
|
exec: onToggleRaiseHand,
|
|
helpDescription: 'keyboardShortcuts.raiseHand'
|
|
},
|
|
isToolbarButtonEnabled('fullscreen', _toolbarButtons) && {
|
|
character: 'S',
|
|
exec: onToggleFullScreen,
|
|
helpDescription: 'keyboardShortcuts.fullScreen'
|
|
},
|
|
isToolbarButtonEnabled('tileview', _toolbarButtons) && {
|
|
character: 'W',
|
|
exec: onToggleTileView,
|
|
helpDescription: 'toolbar.tileViewToggle'
|
|
},
|
|
!_isSpeakerStatsDisabled && isToolbarButtonEnabled('stats', _toolbarButtons) && {
|
|
character: 'T',
|
|
exec: onSpeakerStats,
|
|
helpDescription: 'keyboardShortcuts.showSpeakerStats'
|
|
}
|
|
];
|
|
|
|
KEYBOARD_SHORTCUTS.forEach(shortcut => {
|
|
if (typeof shortcut === 'object') {
|
|
dispatch(registerShortcut({
|
|
character: shortcut.character,
|
|
handler: shortcut.exec,
|
|
helpDescription: shortcut.helpDescription
|
|
}));
|
|
}
|
|
});
|
|
|
|
if (reactionsEnabled) {
|
|
const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
|
|
const onShortcutSendReaction = () => {
|
|
dispatch(addReactionToBuffer(key));
|
|
sendAnalytics(createShortcutEvent(
|
|
`reaction.${key}`
|
|
));
|
|
};
|
|
|
|
return {
|
|
character: REACTIONS[key].shortcutChar,
|
|
exec: onShortcutSendReaction,
|
|
helpDescription: `toolbar.reaction${key.charAt(0).toUpperCase()}${key.slice(1)}`,
|
|
altKey: true
|
|
};
|
|
});
|
|
|
|
REACTION_SHORTCUTS.forEach(shortcut => {
|
|
dispatch(registerShortcut({
|
|
alt: shortcut.altKey,
|
|
character: shortcut.character,
|
|
handler: shortcut.exec,
|
|
helpDescription: shortcut.helpDescription
|
|
}));
|
|
});
|
|
|
|
if (gifsEnabled) {
|
|
const onGifShortcut = () => {
|
|
batch(() => {
|
|
dispatch(toggleReactionsMenuVisibility());
|
|
dispatch(setGifMenuVisibility(true));
|
|
});
|
|
};
|
|
|
|
dispatch(registerShortcut({
|
|
character: 'G',
|
|
handler: onGifShortcut,
|
|
helpDescription: 'keyboardShortcuts.giphyMenu'
|
|
}));
|
|
}
|
|
}
|
|
|
|
return () => {
|
|
[ 'A', 'C', 'D', 'P', 'R', 'S', 'W', 'T', 'G' ].forEach(letter =>
|
|
dispatch(unregisterShortcut(letter)));
|
|
|
|
if (reactionsEnabled) {
|
|
Object.keys(REACTIONS).map(key => REACTIONS[key].shortcutChar)
|
|
.forEach(letter =>
|
|
dispatch(unregisterShortcut(letter, true)));
|
|
}
|
|
};
|
|
}, []);
|
|
};
|