Merge pull request #749 from vector-im/erikj/mute_shortcuts
Add 'm' and 'space' shortcuts for mute/unmuting during a call
This commit is contained in:
		
				commit
				
					
						18139f78d2
					
				
			
		
					 6 changed files with 112 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -42,6 +42,7 @@
 | 
			
		|||
  "Display name": "Display name",
 | 
			
		||||
  "Download debug logs": "Download debug logs",
 | 
			
		||||
  "Element Call Home": "Element Call Home",
 | 
			
		||||
  "Single-key keyboard shortcuts": "Single-key keyboard shortcuts",
 | 
			
		||||
  "Entering room…": "Entering room…",
 | 
			
		||||
  "Exit full screen": "Exit full screen",
 | 
			
		||||
  "Fetching group call timed out.": "Fetching group call timed out.",
 | 
			
		||||
| 
						 | 
				
			
			@ -133,6 +134,7 @@
 | 
			
		|||
  "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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,11 @@ See the License for the specific language governing permissions and
 | 
			
		|||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import { DEFAULT_CONFIG, ConfigOptions, ResolvedConfigOptions } from "./ConfigOptions";
 | 
			
		||||
import {
 | 
			
		||||
  DEFAULT_CONFIG,
 | 
			
		||||
  ConfigOptions,
 | 
			
		||||
  ResolvedConfigOptions,
 | 
			
		||||
} from "./ConfigOptions";
 | 
			
		||||
 | 
			
		||||
export class Config {
 | 
			
		||||
  private static internalInstance: Config;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ import { ReactComponent as MicIcon } from "../icons/Mic.svg";
 | 
			
		|||
import { useEventTarget } from "../useEvents";
 | 
			
		||||
import { Avatar } from "../Avatar";
 | 
			
		||||
import { usePrefersReducedMotion } from "../usePrefersReducedMotion";
 | 
			
		||||
import { getSetting } from "../settings/useSetting";
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  enabled: boolean;
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +135,12 @@ export const PTTButton: React.FC<Props> = ({
 | 
			
		|||
      (e: KeyboardEvent) => {
 | 
			
		||||
        if (e.code === "Space") {
 | 
			
		||||
          if (!enabled) return;
 | 
			
		||||
          // Check if keyboard shortcuts are enabled
 | 
			
		||||
          const keyboardShortcuts = getSetting("keyboard-shortcuts", true);
 | 
			
		||||
          if (!keyboardShortcuts) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
 | 
			
		||||
          hold();
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +155,12 @@ export const PTTButton: React.FC<Props> = ({
 | 
			
		|||
    useCallback(
 | 
			
		||||
      (e: KeyboardEvent) => {
 | 
			
		||||
        if (e.code === "Space") {
 | 
			
		||||
          // Check if keyboard shortcuts are enabled
 | 
			
		||||
          const keyboardShortcuts = getSetting("keyboard-shortcuts", true);
 | 
			
		||||
          if (!keyboardShortcuts) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          e.preventDefault();
 | 
			
		||||
 | 
			
		||||
          unhold();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,8 @@ import { usePageUnload } from "./usePageUnload";
 | 
			
		|||
import { PosthogAnalytics } from "../PosthogAnalytics";
 | 
			
		||||
import { TranslatedError, translatedError } from "../TranslatedError";
 | 
			
		||||
import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
 | 
			
		||||
import { getSetting } from "../settings/useSetting";
 | 
			
		||||
import { useEventTarget } from "../useEvents";
 | 
			
		||||
 | 
			
		||||
export interface UseGroupCallReturnType {
 | 
			
		||||
  state: GroupCallState;
 | 
			
		||||
| 
						 | 
				
			
			@ -298,11 +300,18 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
 | 
			
		|||
    PosthogAnalytics.instance.eventMuteCamera.track(toggleToMute);
 | 
			
		||||
  }, [groupCall]);
 | 
			
		||||
 | 
			
		||||
  const setMicrophoneMuted = useCallback(
 | 
			
		||||
    (setMuted) => {
 | 
			
		||||
      groupCall.setMicrophoneMuted(setMuted);
 | 
			
		||||
      PosthogAnalytics.instance.eventMuteMicrophone.track(setMuted);
 | 
			
		||||
    },
 | 
			
		||||
    [groupCall]
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const toggleMicrophoneMuted = useCallback(() => {
 | 
			
		||||
    const toggleToMute = !groupCall.isMicrophoneMuted();
 | 
			
		||||
    groupCall.setMicrophoneMuted(toggleToMute);
 | 
			
		||||
    PosthogAnalytics.instance.eventMuteMicrophone.track(toggleToMute);
 | 
			
		||||
  }, [groupCall]);
 | 
			
		||||
    setMicrophoneMuted(toggleToMute);
 | 
			
		||||
  }, [groupCall, setMicrophoneMuted]);
 | 
			
		||||
 | 
			
		||||
  const toggleScreensharing = useCallback(async () => {
 | 
			
		||||
    if (!groupCall.isScreensharing()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -395,6 +404,68 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
 | 
			
		|||
    }
 | 
			
		||||
  }, [t]);
 | 
			
		||||
 | 
			
		||||
  const [spacebarHeld, setSpacebarHeld] = useState(false);
 | 
			
		||||
 | 
			
		||||
  useEventTarget(
 | 
			
		||||
    window,
 | 
			
		||||
    "keydown",
 | 
			
		||||
    useCallback(
 | 
			
		||||
      (event: KeyboardEvent) => {
 | 
			
		||||
        // Check if keyboard shortcuts are enabled
 | 
			
		||||
        const keyboardShortcuts = getSetting("keyboard-shortcuts", true);
 | 
			
		||||
        if (!keyboardShortcuts) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (event.key === "m") {
 | 
			
		||||
          toggleMicrophoneMuted();
 | 
			
		||||
        } else if (event.key == "v") {
 | 
			
		||||
          toggleLocalVideoMuted();
 | 
			
		||||
        } else if (event.key === " ") {
 | 
			
		||||
          setSpacebarHeld(true);
 | 
			
		||||
          setMicrophoneMuted(false);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      [
 | 
			
		||||
        toggleLocalVideoMuted,
 | 
			
		||||
        toggleMicrophoneMuted,
 | 
			
		||||
        setMicrophoneMuted,
 | 
			
		||||
        setSpacebarHeld,
 | 
			
		||||
      ]
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  useEventTarget(
 | 
			
		||||
    window,
 | 
			
		||||
    "keyup",
 | 
			
		||||
    useCallback(
 | 
			
		||||
      (event: KeyboardEvent) => {
 | 
			
		||||
        // Check if keyboard shortcuts are enabled
 | 
			
		||||
        const keyboardShortcuts = getSetting("keyboard-shortcuts", true);
 | 
			
		||||
        if (!keyboardShortcuts) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (event.key === " ") {
 | 
			
		||||
          setSpacebarHeld(false);
 | 
			
		||||
          setMicrophoneMuted(true);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      [setMicrophoneMuted, setSpacebarHeld]
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  useEventTarget(
 | 
			
		||||
    window,
 | 
			
		||||
    "blur",
 | 
			
		||||
    useCallback(() => {
 | 
			
		||||
      if (spacebarHeld) {
 | 
			
		||||
        setSpacebarHeld(false);
 | 
			
		||||
        setMicrophoneMuted(true);
 | 
			
		||||
      }
 | 
			
		||||
    }, [setMicrophoneMuted, setSpacebarHeld, spacebarHeld])
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    state,
 | 
			
		||||
    calls,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ import { ReactComponent as OverflowIcon } from "../icons/Overflow.svg";
 | 
			
		|||
import { SelectInput } from "../input/SelectInput";
 | 
			
		||||
import { useMediaHandler } from "./useMediaHandler";
 | 
			
		||||
import {
 | 
			
		||||
  useKeyboardShortcuts,
 | 
			
		||||
  useSpatialAudio,
 | 
			
		||||
  useShowInspector,
 | 
			
		||||
  useOptInAnalytics,
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +60,7 @@ export const SettingsModal = (props: Props) => {
 | 
			
		|||
  const [spatialAudio, setSpatialAudio] = useSpatialAudio();
 | 
			
		||||
  const [showInspector, setShowInspector] = useShowInspector();
 | 
			
		||||
  const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
 | 
			
		||||
  const [keyboardShortcuts, setKeyboardShortcuts] = useKeyboardShortcuts();
 | 
			
		||||
 | 
			
		||||
  const downloadDebugLog = useDownloadDebugLog();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -166,6 +168,20 @@ export const SettingsModal = (props: Props) => {
 | 
			
		|||
              }
 | 
			
		||||
            />
 | 
			
		||||
          </FieldRow>
 | 
			
		||||
          <FieldRow>
 | 
			
		||||
            <InputField
 | 
			
		||||
              id="keyboardShortcuts"
 | 
			
		||||
              label={t("Single-key keyboard shortcuts")}
 | 
			
		||||
              type="checkbox"
 | 
			
		||||
              checked={keyboardShortcuts}
 | 
			
		||||
              description={t(
 | 
			
		||||
                "Whether to enable single-key keyboard shortcuts, e.g. 'm' to mute/unmute the mic."
 | 
			
		||||
              )}
 | 
			
		||||
              onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
 | 
			
		||||
                setKeyboardShortcuts(event.target.checked)
 | 
			
		||||
              }
 | 
			
		||||
            />
 | 
			
		||||
          </FieldRow>
 | 
			
		||||
        </TabItem>
 | 
			
		||||
        <TabItem
 | 
			
		||||
          title={
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,3 +61,5 @@ export const getSetting = <T>(name: string, defaultValue: T): T => {
 | 
			
		|||
export const useSpatialAudio = () => useSetting("spatial-audio", false);
 | 
			
		||||
export const useShowInspector = () => useSetting("show-inspector", false);
 | 
			
		||||
export const useOptInAnalytics = () => useSetting("opt-in-analytics", false);
 | 
			
		||||
export const useKeyboardShortcuts = () =>
 | 
			
		||||
  useSetting("keyboard-shortcuts", true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue