Add toggle raised hand shortcut in group calls

Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
automated-signal
2026-05-19 20:06:45 -05:00
committed by GitHub
parent e0a0cdfa7a
commit bd2c531c13
4 changed files with 62 additions and 35 deletions
+4
View File
@@ -4398,6 +4398,10 @@
"messageformat": "Toggle expanded preview on and off",
"description": "Shown in the shortcuts guide"
},
"icu:Keyboard--toggle-raise-hand": {
"messageformat": "Raise or lower your hand (group calls only)",
"description": "Shown in the shortcuts guide"
},
"icu:Keyboard--accept-video-call": {
"messageformat": "Answer call with video (video calls only)",
"description": "Shown in the calling keyboard shortcuts guide"
+17 -32
View File
@@ -65,7 +65,6 @@ import { CallParticipantCount } from './CallParticipantCount.dom.tsx';
import type { LocalizerType } from '../types/Util.std.ts';
import { NeedsScreenRecordingPermissionsModal } from './NeedsScreenRecordingPermissionsModal.dom.tsx';
import { missingCaseError } from '../util/missingCaseError.std.ts';
import * as KeyboardLayout from '../services/keyboardLayout.dom.ts';
import {
usePresenter,
useActivateSpeakerViewOnPresenting,
@@ -75,6 +74,7 @@ import {
SPEAKING_LINGER_MS,
} from './CallingAudioIndicator.dom.tsx';
import {
makeKeyboardShortcutHandler,
useActiveCallShortcuts,
useKeyboardShortcuts,
} from '../hooks/useKeyboardShortcuts.dom.tsx';
@@ -390,37 +390,6 @@ export function CallScreen({
return clearTimeout.bind(null, timer);
}, [showSelfViewControls, setShowSelfViewControls, selfViewHover]);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent): void => {
let eventHandled = false;
const key = KeyboardLayout.lookup(event);
if (event.shiftKey && (key === 'V' || key === 'v')) {
toggleVideo();
setShowControls(true);
eventHandled = true;
} else if (event.shiftKey && (key === 'M' || key === 'm')) {
toggleAudio();
setShowControls(true);
eventHandled = true;
} else if (event.shiftKey && (key === 'P' || key === 'p')) {
toggleSelfViewExpanded();
eventHandled = true;
}
if (eventHandled) {
event.preventDefault();
event.stopPropagation();
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [setShowControls, toggleAudio, toggleSelfViewExpanded, toggleVideo]);
useEffect(() => {
if (!showReactionPicker) {
return noop;
@@ -956,6 +925,22 @@ export function CallScreen({
toggleParticipants,
]);
useKeyboardShortcuts(
makeKeyboardShortcutHandler('v', { shift: true }, () => {
toggleVideo();
setShowControls(true);
}),
makeKeyboardShortcutHandler('m', { shift: true }, () => {
toggleAudio();
setShowControls(true);
}),
makeKeyboardShortcutHandler('h', { shift: true }, () => {
toggleRaiseHand();
setShowControls(true);
}),
makeKeyboardShortcutHandler('p', { shift: true }, toggleSelfViewExpanded)
);
let remoteParticipantsElement: ReactNode;
switch (activeCall.callMode) {
case CallMode.Direct: {
+6
View File
@@ -35,6 +35,7 @@ type KeyType =
| 'E'
| 'F'
| 'G'
| 'H'
| 'I'
| 'J'
| 'K'
@@ -329,6 +330,11 @@ function getCallingShortcuts(i18n: LocalizerType): Array<ShortcutType> {
description: i18n('icu:Keyboard--toggle-preview'),
keys: [['shift', 'P']],
},
{
id: 'Keyboard--toggle-raise-hand',
description: i18n('icu:Keyboard--toggle-raise-hand'),
keys: [['shift', 'H']],
},
{
id: 'Keyboard--accept-video-call',
description: i18n('icu:Keyboard--accept-video-call'),
+35 -3
View File
@@ -1,7 +1,7 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import lodash from 'lodash';
import { useSelector } from 'react-redux';
import * as KeyboardLayout from '../services/keyboardLayout.dom.ts';
@@ -331,14 +331,46 @@ export function useEditLastMessageSent(
export function useKeyboardShortcuts(
...eventHandlers: Array<KeyboardShortcutHandlerType>
): void {
const handlersRef = useRef(eventHandlers);
handlersRef.current = eventHandlers;
useEffect(() => {
function handleKeydown(ev: KeyboardEvent): void {
eventHandlers.some(eventHandler => eventHandler(ev));
handlersRef.current.some(eventHandler => eventHandler(ev));
}
document.addEventListener('keydown', handleKeydown);
return () => {
document.removeEventListener('keydown', handleKeydown);
};
}, [eventHandlers]);
}, []);
}
/** `key` is matched case-insensitively. */
export function makeKeyboardShortcutHandler(
key: string,
strictMods: Partial<Mods>,
callback: () => unknown
): KeyboardShortcutHandlerType {
return ev => {
const keyPressed = KeyboardLayout.lookup(ev);
if (
hasExactModifiers(ev, {
controlOrMeta: false,
shift: false,
alt: false,
...strictMods,
}) &&
keyPressed?.toLowerCase() === key.toLowerCase()
) {
ev.preventDefault();
ev.stopPropagation();
callback();
return true;
}
return false;
};
}