Keyboard shortcuts

In this guide, you’ll learn how to apply keyboard shortcuts to your Stream Video application. Some users find it much easier to use their keyboard instead of reaching for their mouse/touchpad and having to find an unmute button to be then able click to unmute. In this example we’ll be implementing Ctrl + d (or ⌘ + d on Mac) and Ctrl + e (or ⌘ + e on Mac) shortcuts to mute/unmute your video and audio.

Define custom useKeyboardShortcuts hook

As this hook will introduce keyboard shortcuts related to CallControls (mute/unmute audio) we should ideally invoke it in the same component to group logical parts together for easier debugging later. The same goes for your other keyboard shortcuts you might introduce to your application. Learn how to adjust your CallControls component in the Replacing Call Controls guide.

import { useEffect } from 'react';
import { useCallStateHooks } from '@stream-io/video-react-sdk';

const isMacOS = () => !!navigator.userAgent.match(/(Mac\s?OS)/g)?.length;

export const useKeyboardShortcuts = () => {
  const { useCameraState, useMicrophoneState } = useCallStateHooks();
  const { microphone } = useMicrophoneState();
  const { camera } = useCameraState();

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (
        e.key !== 'd' ||
        (!e.metaKey && isMacOS()) ||
        (!e.ctrlKey && !isMacOS())
      )
        return;
      e.preventDefault();

      microphone.toggle().catch(console.error);
    };

    window.addEventListener('keydown', handleKeyDown);

    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [microphone]);

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (
        e.key !== 'e' ||
        (!e.metaKey && isMacOS()) ||
        (!e.ctrlKey && !isMacOS())
      )
        return;
      e.preventDefault();

      camera.toggle().catch(console.error);
    };

    window.addEventListener('keydown', handleKeyDown);

    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [camera]);
};

Refactor with the use of hotkeys-js

The previous implementation looks a bit messy and hard to read so we’ll refactor this hook with the help of the hotkeys-js which makes shortcut registering and handling much easier.

import { useEffect } from 'react';
import hotkeys from 'hotkeys-js';
import { useCallStateHooks } from '@stream-io/video-react-sdk';

const isMacOS = () => !!navigator.userAgent.match(/(Mac\s?OS)/g)?.length;

export const useKeyboardShortcuts = () => {
  const { useCameraState, useMicrophoneState } = useCallStateHooks();
  const { microphone } = useMicrophoneState();
  const { camera } = useCameraState();

  useEffect(() => {
    const shortcuts = 'cmd+d,ctrl+d';
    hotkeys(shortcuts, (e, ke) => {
      if (isMacOS() && ke.shortcut !== 'cmd+d') return;
      e.preventDefault();

      microphone.toggle().catch(console.error);
    });

    return () => hotkeys.unbind(shortcuts);
  }, [microphone]);

  useEffect(() => {
    const shortcuts = 'cmd+e,ctrl+e';
    hotkeys(shortcuts, (e, ke) => {
      if (isMacOS() && ke.shortcut !== 'cmd+e') return;
      e.preventDefault();

      camera.toggle().catch(console.error);
    });

    return () => hotkeys.unbind(shortcuts);
  }, [camera]);
};
© Getstream.io, Inc. All Rights Reserved.