diff --git a/res/css/views/voip/_CallContainer.scss b/res/css/views/voip/_CallContainer.scss index 8262075559..168a8bb74b 100644 --- a/res/css/views/voip/_CallContainer.scss +++ b/res/css/views/voip/_CallContainer.scss @@ -98,5 +98,29 @@ limitations under the License. line-height: $font-24px; } } + + .mx_IncomingCallBox_iconButton { + position: absolute; + right: 8px; + + &::before { + content: ''; + + height: 20px; + width: 20px; + background-color: $icon-button-color; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + } + } + + .mx_IncomingCallBox_silence::before { + mask-image: url('$(res)/img/voip/silence.svg'); + } + + .mx_IncomingCallBox_unSilence::before { + mask-image: url('$(res)/img/voip/un-silence.svg'); + } } } diff --git a/res/img/voip/silence.svg b/res/img/voip/silence.svg new file mode 100644 index 0000000000..332932dfff --- /dev/null +++ b/res/img/voip/silence.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/un-silence.svg b/res/img/voip/un-silence.svg new file mode 100644 index 0000000000..c00b366f84 --- /dev/null +++ b/res/img/voip/un-silence.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index bf7cb3473d..448b1cb780 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -99,7 +99,7 @@ const CHECK_PROTOCOLS_ATTEMPTS = 3; // (and store the ID of their native room) export const VIRTUAL_ROOM_EVENT_TYPE = 'im.vector.is_virtual_room'; -enum AudioID { +export enum AudioID { Ring = 'ringAudio', Ringback = 'ringbackAudio', CallEnd = 'callendAudio', diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx index 2abdc0641d..a0660318bc 100644 --- a/src/components/views/voip/IncomingCallBox.tsx +++ b/src/components/views/voip/IncomingCallBox.tsx @@ -21,17 +21,20 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg'; import dis from '../../../dispatcher/dispatcher'; import { _t } from '../../../languageHandler'; import { ActionPayload } from '../../../dispatcher/payloads'; -import CallHandler from '../../../CallHandler'; +import CallHandler, { AudioID } from '../../../CallHandler'; import RoomAvatar from '../avatars/RoomAvatar'; import FormButton from '../elements/FormButton'; import { CallState } from 'matrix-js-sdk/src/webrtc/call'; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; +import classNames from 'classnames'; interface IProps { } interface IState { incomingCall: any; + silenced: boolean; } @replaceableComponent("views.voip.IncomingCallBox") @@ -44,6 +47,7 @@ export default class IncomingCallBox extends React.Component { this.dispatcherRef = dis.register(this.onAction); this.state = { incomingCall: null, + silenced: false, }; } @@ -58,6 +62,7 @@ export default class IncomingCallBox extends React.Component { if (call && call.state === CallState.Ringing) { this.setState({ incomingCall: call, + silenced: false, // Reset silenced state for new call }); } else { this.setState({ @@ -84,6 +89,13 @@ export default class IncomingCallBox extends React.Component { }); }; + private onSilenceClick: React.MouseEventHandler = (e) => { + e.stopPropagation(); + const newState = !this.state.silenced + this.setState({silenced: newState}); + newState ? CallHandler.sharedInstance().pause(AudioID.Ring) : CallHandler.sharedInstance().play(AudioID.Ring); + } + public render() { if (!this.state.incomingCall) { return null; @@ -107,6 +119,12 @@ export default class IncomingCallBox extends React.Component { } } + const silenceClass = classNames({ + "mx_IncomingCallBox_iconButton": true, + "mx_IncomingCallBox_unSilence": this.state.silenced, + "mx_IncomingCallBox_silence": !this.state.silenced, + }); + return
{

{caller}

{incomingCallText}

+