diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json index 389eeb7..6e91a53 100644 --- a/public/locales/en-GB/app.json +++ b/public/locales/en-GB/app.json @@ -106,7 +106,6 @@ "Show call inspector": "Show call inspector", "Sign in": "Sign in", "Sign out": "Sign out", - "Single-key keyboard shortcuts": "Single-key keyboard shortcuts", "Spatial audio": "Spatial audio", "Speaker": "Speaker", "Speaker {{n}}": "Speaker {{n}}", @@ -138,7 +137,6 @@ "Walkie-talkie call": "Walkie-talkie call", "Walkie-talkie call name": "Walkie-talkie call name", "WebRTC is not supported or is being blocked in this browser.": "WebRTC is not supported or is being blocked in this browser.", - "Whether to enable single-key keyboard shortcuts, e.g. 'm' to mute/unmute the mic.": "Whether to enable single-key keyboard shortcuts, e.g. 'm' to mute/unmute the mic.", "Yes, join call": "Yes, join call", "You can't talk at the same time": "You can't talk at the same time", "Your recent calls": "Your recent calls" diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index cf1e4dc..1202534 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -157,7 +157,7 @@ export function InCallView({ const { hideScreensharing } = useUrlParams(); useCallViewKeyboardShortcuts( - !feedbackModalState.isOpen, + containerRef1, toggleMicrophoneMuted, toggleLocalVideoMuted, setMicrophoneMuted diff --git a/src/settings/SettingsModal.tsx b/src/settings/SettingsModal.tsx index 6e38b5f..b126bb8 100644 --- a/src/settings/SettingsModal.tsx +++ b/src/settings/SettingsModal.tsx @@ -28,7 +28,6 @@ import { ReactComponent as OverflowIcon } from "../icons/Overflow.svg"; import { SelectInput } from "../input/SelectInput"; import { useMediaHandler } from "./useMediaHandler"; import { - useKeyboardShortcuts, useSpatialAudio, useShowInspector, useOptInAnalytics, @@ -65,7 +64,6 @@ export const SettingsModal = (props: Props) => { const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics(); const [developerSettingsTab, setDeveloperSettingsTab] = useDeveloperSettingsTab(); - const [keyboardShortcuts, setKeyboardShortcuts] = useKeyboardShortcuts(); const [newGrid, setNewGrid] = useNewGrid(); const downloadDebugLog = useDownloadDebugLog(); @@ -176,21 +174,6 @@ export const SettingsModal = (props: Props) => { } > -

Keyboard

- - ) => - setKeyboardShortcuts(event.target.checked) - } - /> -

Analytics

=> { return [false, null]; }; -export const useKeyboardShortcuts = () => - useSetting("keyboard-shortcuts", true); - export const useNewGrid = () => useSetting("new-grid", false); export const useDeveloperSettingsTab = () => diff --git a/src/useCallViewKeyboardShortcuts.ts b/src/useCallViewKeyboardShortcuts.ts index 8a247d0..11ea8f0 100644 --- a/src/useCallViewKeyboardShortcuts.ts +++ b/src/useCallViewKeyboardShortcuts.ts @@ -14,47 +14,55 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useCallback, useState } from "react"; +import { RefObject, useCallback, useRef } from "react"; -import { getSetting } from "./settings/useSetting"; import { useEventTarget } from "./useEvents"; +/** + * Determines whether focus is in the same part of the tree as the given + * element (specifically, if an ancestor or descendant of it is focused). + */ +const mayReceiveKeyEvents = (e: HTMLElement): boolean => { + const focusedElement = document.activeElement; + return ( + focusedElement !== null && + (focusedElement.contains(e) || e.contains(focusedElement)) + ); +}; + export function useCallViewKeyboardShortcuts( - enabled: boolean, + focusElement: RefObject, toggleMicrophoneMuted: () => void, toggleLocalVideoMuted: () => void, setMicrophoneMuted: (muted: boolean) => void ) { - const [spacebarHeld, setSpacebarHeld] = useState(false); + const spacebarHeld = useRef(false); + + // These event handlers are set on the window because we want users to be able + // to trigger them without going to the trouble of focusing something useEventTarget( window, "keydown", useCallback( (event: KeyboardEvent) => { - if (!enabled) return; - // Check if keyboard shortcuts are enabled - const keyboardShortcuts = getSetting("keyboard-shortcuts", true); - if (!keyboardShortcuts) { - return; - } + if (focusElement.current === null) return; + if (!mayReceiveKeyEvents(focusElement.current)) return; if (event.key === "m") { toggleMicrophoneMuted(); } else if (event.key == "v") { toggleLocalVideoMuted(); - } else if (event.key === " " && !spacebarHeld) { - setSpacebarHeld(true); + } else if (event.key === " " && !spacebarHeld.current) { + spacebarHeld.current = true; setMicrophoneMuted(false); } }, [ - enabled, - spacebarHeld, + focusElement, toggleLocalVideoMuted, toggleMicrophoneMuted, setMicrophoneMuted, - setSpacebarHeld, ] ) ); @@ -64,19 +72,15 @@ export function useCallViewKeyboardShortcuts( "keyup", useCallback( (event: KeyboardEvent) => { - if (!enabled) return; - // Check if keyboard shortcuts are enabled - const keyboardShortcuts = getSetting("keyboard-shortcuts", true); - if (!keyboardShortcuts) { - return; - } + if (focusElement.current === null) return; + if (!mayReceiveKeyEvents(focusElement.current)) return; if (event.key === " ") { - setSpacebarHeld(false); + spacebarHeld.current = false; setMicrophoneMuted(true); } }, - [enabled, setMicrophoneMuted, setSpacebarHeld] + [focusElement, setMicrophoneMuted] ) ); @@ -85,9 +89,9 @@ export function useCallViewKeyboardShortcuts( "blur", useCallback(() => { if (spacebarHeld) { - setSpacebarHeld(false); + spacebarHeld.current = false; setMicrophoneMuted(true); } - }, [setMicrophoneMuted, setSpacebarHeld, spacebarHeld]) + }, [setMicrophoneMuted, spacebarHeld]) ); }