mirror of https://github.com/vector-im/riot-web
Merge pull request #6181 from pvagner/voip-a11y
Make call control buttons accessible to screen reader userspull/21833/head
commit
3b73c17465
|
@ -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")}
|
||||||
|
|
|
@ -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>",
|
||||||
|
|
Loading…
Reference in New Issue