Merge pull request #6181 from pvagner/voip-a11y

Make call control buttons accessible to screen reader users
pull/21833/head
Travis Ralston 2021-08-05 13:36:17 -06:00 committed by GitHub
commit 3b73c17465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 11 deletions

View File

@ -23,11 +23,16 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t, _td } from '../../../languageHandler'; import { _t, _td } from '../../../languageHandler';
import VideoFeed from './VideoFeed'; import VideoFeed from './VideoFeed';
import RoomAvatar from "../avatars/RoomAvatar"; import RoomAvatar from "../avatars/RoomAvatar";
import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/webrtc/call'; import { CallEvent, CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
import classNames from 'classnames'; import classNames from 'classnames';
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import { isOnlyCtrlOrCmdKeyEvent, Key } from '../../../Keyboard'; import { isOnlyCtrlOrCmdKeyEvent, Key } from '../../../Keyboard';
import { alwaysAboveLeftOf, alwaysAboveRightOf, ChevronFace, ContextMenuButton } from '../../structures/ContextMenu'; import {
alwaysAboveLeftOf,
alwaysAboveRightOf,
ChevronFace,
ContextMenuTooltipButton,
} from '../../structures/ContextMenu';
import CallContextMenu from '../context_menus/CallContextMenu'; import CallContextMenu from '../context_menus/CallContextMenu';
import { avatarUrlForMember } from '../../../Avatar'; import { avatarUrlForMember } from '../../../Avatar';
import DialpadContextMenu from '../context_menus/DialpadContextMenu'; import DialpadContextMenu from '../context_menus/DialpadContextMenu';
@ -37,6 +42,8 @@ import DesktopCapturerSourcePicker from "../elements/DesktopCapturerSourcePicker
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/src/webrtc/callEventTypes'; import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/src/webrtc/callEventTypes';
import CallViewSidebar from './CallViewSidebar'; import CallViewSidebar from './CallViewSidebar';
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import { Alignment } from "../elements/Tooltip";
interface IProps { interface IProps {
// The call for us to display // The call for us to display
@ -75,6 +82,8 @@ interface IState {
sidebarShown: boolean; sidebarShown: boolean;
} }
const tooltipYOffset = -24;
function getFullScreenElement() { function getFullScreenElement() {
return ( return (
document.fullscreenElement || document.fullscreenElement ||
@ -115,7 +124,6 @@ export default class CallView extends React.Component<IProps, IState> {
private controlsHideTimer: number = null; private controlsHideTimer: number = null;
private dialpadButton = createRef<HTMLDivElement>(); private dialpadButton = createRef<HTMLDivElement>();
private contextMenuButton = createRef<HTMLDivElement>(); private contextMenuButton = createRef<HTMLDivElement>();
private contextMenu = createRef<HTMLDivElement>();
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -479,9 +487,12 @@ export default class CallView extends React.Component<IProps, IState> {
let vidMuteButton; let vidMuteButton;
if (this.props.call.type === CallType.Video) { if (this.props.call.type === CallType.Video) {
vidMuteButton = ( vidMuteButton = (
<AccessibleButton <AccessibleTooltipButton
className={vidClasses} className={vidClasses}
onClick={this.onVidMuteClick} onClick={this.onVidMuteClick}
title={this.state.vidMuted ? _t("Start the camera") : _t("Stop the camera")}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
); );
} }
@ -496,9 +507,15 @@ export default class CallView extends React.Component<IProps, IState> {
this.props.call.state === CallState.Connected this.props.call.state === CallState.Connected
) { ) {
screensharingButton = ( screensharingButton = (
<AccessibleButton <AccessibleTooltipButton
className={screensharingClasses} className={screensharingClasses}
onClick={this.onScreenshareClick} onClick={this.onScreenshareClick}
title={this.state.screensharing
? _t("Stop sharing your screen")
: _t("Start sharing your screen")
}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
); );
} }
@ -518,6 +535,7 @@ export default class CallView extends React.Component<IProps, IState> {
<AccessibleButton <AccessibleButton
className={sidebarButtonClasses} className={sidebarButtonClasses}
onClick={this.onToggleSidebar} onClick={this.onToggleSidebar}
aria-label={this.state.sidebarShown ? _t("Hide sidebar") : _t("Show sidebar")}
/> />
); );
} }
@ -526,22 +544,28 @@ export default class CallView extends React.Component<IProps, IState> {
let contextMenuButton; let contextMenuButton;
if (this.state.callState === CallState.Connected) { if (this.state.callState === CallState.Connected) {
contextMenuButton = ( contextMenuButton = (
<ContextMenuButton <ContextMenuTooltipButton
className="mx_CallView_callControls_button mx_CallView_callControls_button_more" className="mx_CallView_callControls_button mx_CallView_callControls_button_more"
onClick={this.onMoreClick} onClick={this.onMoreClick}
inputRef={this.contextMenuButton} inputRef={this.contextMenuButton}
isExpanded={this.state.showMoreMenu} isExpanded={this.state.showMoreMenu}
title={_t("More")}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
); );
} }
let dialpadButton; let dialpadButton;
if (this.state.callState === CallState.Connected && this.props.call.opponentSupportsDTMF()) { if (this.state.callState === CallState.Connected && this.props.call.opponentSupportsDTMF()) {
dialpadButton = ( dialpadButton = (
<ContextMenuButton <ContextMenuTooltipButton
className="mx_CallView_callControls_button mx_CallView_callControls_dialpad" className="mx_CallView_callControls_button mx_CallView_callControls_dialpad"
inputRef={this.dialpadButton} inputRef={this.dialpadButton}
onClick={this.onDialpadClick} onClick={this.onDialpadClick}
isExpanded={this.state.showDialpad} isExpanded={this.state.showDialpad}
title={_t("Dialpad")}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
); );
} }
@ -587,9 +611,12 @@ export default class CallView extends React.Component<IProps, IState> {
{ dialPad } { dialPad }
{ contextMenu } { contextMenu }
{ dialpadButton } { dialpadButton }
<AccessibleButton <AccessibleTooltipButton
className={micClasses} className={micClasses}
onClick={this.onMicMuteClick} onClick={this.onMicMuteClick}
title={this.state.micMuted ? _t("Unmute the microphone") : _t("Mute the microphone")}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
{ vidMuteButton } { vidMuteButton }
<div className={micCacheClasses} /> <div className={micCacheClasses} />
@ -597,9 +624,12 @@ export default class CallView extends React.Component<IProps, IState> {
{ screensharingButton } { screensharingButton }
{ sidebarButton } { sidebarButton }
{ contextMenuButton } { contextMenuButton }
<AccessibleButton <AccessibleTooltipButton
className="mx_CallView_callControls_button mx_CallView_callControls_button_hangup" className="mx_CallView_callControls_button mx_CallView_callControls_button_hangup"
onClick={this.onHangupClick} onClick={this.onHangupClick}
title={_t("Hangup")}
alignment={Alignment.Top}
yOffset={tooltipYOffset}
/> />
</div> </div>
); );
@ -824,7 +854,7 @@ export default class CallView extends React.Component<IProps, IState> {
let fullScreenButton; let fullScreenButton;
if (!this.props.pipMode) { if (!this.props.pipMode) {
fullScreenButton = ( fullScreenButton = (
<div <AccessibleTooltipButton
className="mx_CallView_header_button mx_CallView_header_button_fullscreen" className="mx_CallView_header_button mx_CallView_header_button_fullscreen"
onClick={this.onFullscreenClick} onClick={this.onFullscreenClick}
title={_t("Fill Screen")} title={_t("Fill Screen")}
@ -834,7 +864,7 @@ export default class CallView extends React.Component<IProps, IState> {
let expandButton; let expandButton;
if (this.props.pipMode) { if (this.props.pipMode) {
expandButton = <div expandButton = <AccessibleTooltipButton
className="mx_CallView_header_button mx_CallView_header_button_expand" className="mx_CallView_header_button mx_CallView_header_button_expand"
onClick={this.onExpandClick} onClick={this.onExpandClick}
title={_t("Return to call")} title={_t("Return to call")}

View File

@ -904,6 +904,17 @@
"sends snowfall": "sends snowfall", "sends snowfall": "sends snowfall",
"Sends the given message with a space themed effect": "Sends the given message with a space themed effect", "Sends the given message with a space themed effect": "Sends the given message with a space themed effect",
"sends space invaders": "sends space invaders", "sends space invaders": "sends space invaders",
"Start the camera": "Start the camera",
"Stop the camera": "Stop the camera",
"Stop sharing your screen": "Stop sharing your screen",
"Start sharing your screen": "Start sharing your screen",
"Hide sidebar": "Hide sidebar",
"Show sidebar": "Show sidebar",
"More": "More",
"Dialpad": "Dialpad",
"Unmute the microphone": "Unmute the microphone",
"Mute the microphone": "Mute the microphone",
"Hangup": "Hangup",
"unknown person": "unknown person", "unknown person": "unknown person",
"Consulting with %(transferTarget)s. <a>Transfer to %(transferee)s</a>": "Consulting with %(transferTarget)s. <a>Transfer to %(transferee)s</a>", "Consulting with %(transferTarget)s. <a>Transfer to %(transferee)s</a>": "Consulting with %(transferTarget)s. <a>Transfer to %(transferee)s</a>",
"You held the call <a>Switch</a>": "You held the call <a>Switch</a>", "You held the call <a>Switch</a>": "You held the call <a>Switch</a>",