Improve interactions to hide/show the footer

This fixes a few different usability issues with the footer:

- When tapping one of the footer buttons, the footer would be dismissed rather than activating the button.
- When the footer was hidden, you could still tap the buttons.
- Interacting with controls in the footer would not reset the timer that hides it, leading to a feeling that the footer can disappear out from under you.
This commit is contained in:
Robin
2024-11-08 10:23:19 -05:00
parent 1df2e0c48f
commit 68d71a8329
3 changed files with 67 additions and 23 deletions

View File

@@ -261,12 +261,22 @@ export const InCallView: FC<InCallViewProps> = ({
}, [vm]);
const onTouchCancel = useCallback(() => (touchStart.current = null), []);
// We also need to tell the layout toggle to prevent touch events from
// bubbling up, or else the controls will be dismissed before a change event
// can be registered on the toggle
const onLayoutToggleTouchEnd = useCallback(
(e: TouchEvent) => e.stopPropagation(),
[],
// We also need to tell the footer controls to prevent touch events from
// bubbling up, or else the footer will be dismissed before a click/change
// event can be registered on the control
const onControlsTouchEnd = useCallback(
(e: TouchEvent) => {
// Somehow applying pointer-events: none to the controls when the footer
// is hidden is not enough to stop clicks from happening as the footer
// becomes visible, so we check manually whether the footer is shown
if (showFooter) {
e.stopPropagation();
vm.tapControls();
} else {
e.preventDefault();
}
},
[vm, showFooter],
);
const onPointerMove = useCallback(
@@ -528,6 +538,7 @@ export const InCallView: FC<InCallViewProps> = ({
key="audio"
muted={!muteStates.audio.enabled}
onClick={toggleMicrophone}
onTouchEnd={onControlsTouchEnd}
disabled={muteStates.audio.setEnabled === null}
data-testid="incall_mute"
/>,
@@ -535,6 +546,7 @@ export const InCallView: FC<InCallViewProps> = ({
key="video"
muted={!muteStates.video.enabled}
onClick={toggleCamera}
onTouchEnd={onControlsTouchEnd}
disabled={muteStates.video.setEnabled === null}
data-testid="incall_videomute"
/>,
@@ -545,6 +557,7 @@ export const InCallView: FC<InCallViewProps> = ({
key="switch_camera"
className={styles.switchCamera}
onClick={switchCamera}
onTouchEnd={onControlsTouchEnd}
/>,
);
if (canScreenshare && !hideScreensharing) {
@@ -554,6 +567,7 @@ export const InCallView: FC<InCallViewProps> = ({
className={styles.shareScreen}
enabled={isScreenShareEnabled}
onClick={toggleScreensharing}
onTouchEnd={onControlsTouchEnd}
data-testid="incall_screenshare"
/>,
);
@@ -565,11 +579,18 @@ export const InCallView: FC<InCallViewProps> = ({
className={styles.raiseHand}
client={client}
rtcSession={rtcSession}
onTouchEnd={onControlsTouchEnd}
/>,
);
}
if (layout.type !== "pip")
buttons.push(<SettingsButton key="settings" onClick={openSettings} />);
buttons.push(
<SettingsButton
key="settings"
onClick={openSettings}
onTouchEnd={onControlsTouchEnd}
/>,
);
buttons.push(
<EndCallButton
@@ -577,6 +598,7 @@ export const InCallView: FC<InCallViewProps> = ({
onClick={function (): void {
onLeave();
}}
onTouchEnd={onControlsTouchEnd}
data-testid="incall_leave"
/>,
);
@@ -604,7 +626,7 @@ export const InCallView: FC<InCallViewProps> = ({
className={styles.layout}
layout={gridMode}
setLayout={setGridMode}
onTouchEnd={onLayoutToggleTouchEnd}
onTouchEnd={onControlsTouchEnd}
/>
)}
</div>