Disable keyboard shortcuts when feedback modal is open
This commit is contained in:
		
					parent
					
						
							
								30688715cd
							
						
					
				
			
			
				commit
				
					
						9ba4ce429f
					
				
			
		
					 4 changed files with 106 additions and 64 deletions
				
			
		|  | @ -75,6 +75,7 @@ export function GroupCallView({ | ||||||
|     toggleLocalVideoMuted, |     toggleLocalVideoMuted, | ||||||
|     toggleMicrophoneMuted, |     toggleMicrophoneMuted, | ||||||
|     toggleScreensharing, |     toggleScreensharing, | ||||||
|  |     setMicrophoneMuted, | ||||||
|     requestingScreenshare, |     requestingScreenshare, | ||||||
|     isScreensharing, |     isScreensharing, | ||||||
|     screenshareFeeds, |     screenshareFeeds, | ||||||
|  | @ -251,6 +252,7 @@ export function GroupCallView({ | ||||||
|           localVideoMuted={localVideoMuted} |           localVideoMuted={localVideoMuted} | ||||||
|           toggleLocalVideoMuted={toggleLocalVideoMuted} |           toggleLocalVideoMuted={toggleLocalVideoMuted} | ||||||
|           toggleMicrophoneMuted={toggleMicrophoneMuted} |           toggleMicrophoneMuted={toggleMicrophoneMuted} | ||||||
|  |           setMicrophoneMuted={setMicrophoneMuted} | ||||||
|           userMediaFeeds={userMediaFeeds} |           userMediaFeeds={userMediaFeeds} | ||||||
|           activeSpeaker={activeSpeaker} |           activeSpeaker={activeSpeaker} | ||||||
|           onLeave={onLeave} |           onLeave={onLeave} | ||||||
|  |  | ||||||
|  | @ -63,6 +63,7 @@ import { usePrefersReducedMotion } from "../usePrefersReducedMotion"; | ||||||
| import { ParticipantInfo } from "./useGroupCall"; | import { ParticipantInfo } from "./useGroupCall"; | ||||||
| import { TileDescriptor } from "../video-grid/TileDescriptor"; | import { TileDescriptor } from "../video-grid/TileDescriptor"; | ||||||
| import { AudioSink } from "../video-grid/AudioSink"; | import { AudioSink } from "../video-grid/AudioSink"; | ||||||
|  | import { useKeyboardShortcuts } from "../useKeyboardShortcuts"; | ||||||
| 
 | 
 | ||||||
| const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); | const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); | ||||||
| // There is currently a bug in Safari our our code with cloning and sending MediaStreams
 | // There is currently a bug in Safari our our code with cloning and sending MediaStreams
 | ||||||
|  | @ -81,6 +82,7 @@ interface Props { | ||||||
|   toggleLocalVideoMuted: () => void; |   toggleLocalVideoMuted: () => void; | ||||||
|   toggleMicrophoneMuted: () => void; |   toggleMicrophoneMuted: () => void; | ||||||
|   toggleScreensharing: () => void; |   toggleScreensharing: () => void; | ||||||
|  |   setMicrophoneMuted: (muted: boolean) => void; | ||||||
|   userMediaFeeds: CallFeed[]; |   userMediaFeeds: CallFeed[]; | ||||||
|   activeSpeaker: CallFeed | null; |   activeSpeaker: CallFeed | null; | ||||||
|   onLeave: () => void; |   onLeave: () => void; | ||||||
|  | @ -101,6 +103,7 @@ export function InCallView({ | ||||||
|   localVideoMuted, |   localVideoMuted, | ||||||
|   toggleLocalVideoMuted, |   toggleLocalVideoMuted, | ||||||
|   toggleMicrophoneMuted, |   toggleMicrophoneMuted, | ||||||
|  |   setMicrophoneMuted, | ||||||
|   userMediaFeeds, |   userMediaFeeds, | ||||||
|   activeSpeaker, |   activeSpeaker, | ||||||
|   onLeave, |   onLeave, | ||||||
|  | @ -141,6 +144,13 @@ export function InCallView({ | ||||||
| 
 | 
 | ||||||
|   const { hideScreensharing } = useUrlParams(); |   const { hideScreensharing } = useUrlParams(); | ||||||
| 
 | 
 | ||||||
|  |   useKeyboardShortcuts( | ||||||
|  |     !feedbackModalState.isOpen, | ||||||
|  |     toggleMicrophoneMuted, | ||||||
|  |     toggleLocalVideoMuted, | ||||||
|  |     setMicrophoneMuted | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     widget?.api.transport.send( |     widget?.api.transport.send( | ||||||
|       layout === "freedom" |       layout === "freedom" | ||||||
|  |  | ||||||
|  | @ -32,8 +32,6 @@ import { usePageUnload } from "./usePageUnload"; | ||||||
| import { PosthogAnalytics } from "../PosthogAnalytics"; | import { PosthogAnalytics } from "../PosthogAnalytics"; | ||||||
| import { TranslatedError, translatedError } from "../TranslatedError"; | import { TranslatedError, translatedError } from "../TranslatedError"; | ||||||
| import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget"; | import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget"; | ||||||
| import { getSetting } from "../settings/useSetting"; |  | ||||||
| import { useEventTarget } from "../useEvents"; |  | ||||||
| 
 | 
 | ||||||
| export enum ConnectionState { | export enum ConnectionState { | ||||||
|   EstablishingCall = "establishing call", // call hasn't been established yet
 |   EstablishingCall = "establishing call", // call hasn't been established yet
 | ||||||
|  | @ -60,6 +58,7 @@ export interface UseGroupCallReturnType { | ||||||
|   toggleLocalVideoMuted: () => void; |   toggleLocalVideoMuted: () => void; | ||||||
|   toggleMicrophoneMuted: () => void; |   toggleMicrophoneMuted: () => void; | ||||||
|   toggleScreensharing: () => void; |   toggleScreensharing: () => void; | ||||||
|  |   setMicrophoneMuted: (muted: boolean) => void; | ||||||
|   requestingScreenshare: boolean; |   requestingScreenshare: boolean; | ||||||
|   isScreensharing: boolean; |   isScreensharing: boolean; | ||||||
|   screenshareFeeds: CallFeed[]; |   screenshareFeeds: CallFeed[]; | ||||||
|  | @ -472,68 +471,6 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType { | ||||||
|     } |     } | ||||||
|   }, [t, updateState]); |   }, [t, updateState]); | ||||||
| 
 | 
 | ||||||
|   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 { |   return { | ||||||
|     state, |     state, | ||||||
|     localCallFeed, |     localCallFeed, | ||||||
|  | @ -548,6 +485,7 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType { | ||||||
|     toggleLocalVideoMuted, |     toggleLocalVideoMuted, | ||||||
|     toggleMicrophoneMuted, |     toggleMicrophoneMuted, | ||||||
|     toggleScreensharing, |     toggleScreensharing, | ||||||
|  |     setMicrophoneMuted, | ||||||
|     requestingScreenshare, |     requestingScreenshare, | ||||||
|     isScreensharing, |     isScreensharing, | ||||||
|     screenshareFeeds, |     screenshareFeeds, | ||||||
|  |  | ||||||
							
								
								
									
										92
									
								
								src/useKeyboardShortcuts.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/useKeyboardShortcuts.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2022-2023 New Vector Ltd | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | import { useCallback, useState } from "react"; | ||||||
|  | 
 | ||||||
|  | import { getSetting } from "./settings/useSetting"; | ||||||
|  | import { useEventTarget } from "./useEvents"; | ||||||
|  | 
 | ||||||
|  | export function useKeyboardShortcuts( | ||||||
|  |   enabled: boolean, | ||||||
|  |   toggleMicrophoneMuted: () => void, | ||||||
|  |   toggleLocalVideoMuted: () => void, | ||||||
|  |   setMicrophoneMuted: (muted: boolean) => void | ||||||
|  | ) { | ||||||
|  |   const [spacebarHeld, setSpacebarHeld] = useState(false); | ||||||
|  | 
 | ||||||
|  |   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 (event.key === "m") { | ||||||
|  |           toggleMicrophoneMuted(); | ||||||
|  |         } else if (event.key == "v") { | ||||||
|  |           toggleLocalVideoMuted(); | ||||||
|  |         } else if (event.key === " ") { | ||||||
|  |           setSpacebarHeld(true); | ||||||
|  |           setMicrophoneMuted(false); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       [ | ||||||
|  |         enabled, | ||||||
|  |         toggleLocalVideoMuted, | ||||||
|  |         toggleMicrophoneMuted, | ||||||
|  |         setMicrophoneMuted, | ||||||
|  |         setSpacebarHeld, | ||||||
|  |       ] | ||||||
|  |     ) | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   useEventTarget( | ||||||
|  |     window, | ||||||
|  |     "keyup", | ||||||
|  |     useCallback( | ||||||
|  |       (event: KeyboardEvent) => { | ||||||
|  |         if (!enabled) return; | ||||||
|  |         // Check if keyboard shortcuts are enabled
 | ||||||
|  |         const keyboardShortcuts = getSetting("keyboard-shortcuts", true); | ||||||
|  |         if (!keyboardShortcuts) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (event.key === " ") { | ||||||
|  |           setSpacebarHeld(false); | ||||||
|  |           setMicrophoneMuted(true); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       [enabled, setMicrophoneMuted, setSpacebarHeld] | ||||||
|  |     ) | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   useEventTarget( | ||||||
|  |     window, | ||||||
|  |     "blur", | ||||||
|  |     useCallback(() => { | ||||||
|  |       if (spacebarHeld) { | ||||||
|  |         setSpacebarHeld(false); | ||||||
|  |         setMicrophoneMuted(true); | ||||||
|  |       } | ||||||
|  |     }, [setMicrophoneMuted, setSpacebarHeld, spacebarHeld]) | ||||||
|  |   ); | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue