mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 12:45:11 +08:00
Remove call bar
Also hide video mute button on voice calls (awaiting clarification from design) and fix mute keyboard shortcuts by moving them out of roomview & into callview.
This commit is contained in:
parent
41e885dd67
commit
50965e41eb
@ -19,57 +19,6 @@ limitations under the License.
|
|||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */
|
|
||||||
.mx_RoomStatusBar_indicator {
|
|
||||||
padding-left: 17px;
|
|
||||||
padding-right: 12px;
|
|
||||||
margin-left: -73px;
|
|
||||||
margin-top: 15px;
|
|
||||||
float: left;
|
|
||||||
width: 24px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomStatusBar_callBar {
|
|
||||||
height: 50px;
|
|
||||||
line-height: $font-50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomStatusBar_placeholderIndicator span {
|
|
||||||
color: $primary-fg-color;
|
|
||||||
opacity: 0.5;
|
|
||||||
position: relative;
|
|
||||||
top: -4px;
|
|
||||||
/*
|
|
||||||
animation-duration: 1s;
|
|
||||||
animation-name: bounce;
|
|
||||||
animation-direction: alternate;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomStatusBar_placeholderIndicator span:nth-child(1) {
|
|
||||||
animation-delay: 0.3s;
|
|
||||||
}
|
|
||||||
.mx_RoomStatusBar_placeholderIndicator span:nth-child(2) {
|
|
||||||
animation-delay: 0.6s;
|
|
||||||
}
|
|
||||||
.mx_RoomStatusBar_placeholderIndicator span:nth-child(3) {
|
|
||||||
animation-delay: 0.9s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bounce {
|
|
||||||
from {
|
|
||||||
opacity: 0.5;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 0.2;
|
|
||||||
top: -3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomStatusBar_typingIndicatorAvatars {
|
.mx_RoomStatusBar_typingIndicatorAvatars {
|
||||||
width: 52px;
|
width: 52px;
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
@ -162,11 +111,6 @@ limitations under the License.
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomStatusBar_callBar {
|
|
||||||
height: 40px;
|
|
||||||
line-height: $font-40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomStatusBar_typingBar {
|
.mx_RoomStatusBar_typingBar {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: $font-40px;
|
line-height: $font-40px;
|
||||||
|
@ -145,6 +145,9 @@ limitations under the License.
|
|||||||
|
|
||||||
.mx_CallView_callControls_button {
|
.mx_CallView_callControls_button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
@ -184,9 +187,6 @@ limitations under the License.
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mx_CallView_callControls_button_hangup {
|
.mx_CallView_callControls_button_hangup {
|
||||||
margin-left: 16px;
|
|
||||||
margin-right: 16px;
|
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
background-image: url('$(res)/img/voip_buttons/hangup.svg');
|
background-image: url('$(res)/img/voip_buttons/hangup.svg');
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M16 9C16 9 17 10.2857 17 12C17 13.7143 16 15 16 15" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<path d="M19 6C19 6 21 8.57143 21 12C21 15.4286 19 18 19 18" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<rect x="2" y="8" width="11" height="8" rx="2" fill="white"/>
|
|
||||||
<path d="M7 8L11.3598 4.36682C12.0111 3.82405 13 4.2872 13 5.13504V18.865C13 19.7128 12.0111 20.176 11.3598 19.6332L7 16V8Z" fill="white"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 541 B |
@ -18,13 +18,11 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Matrix from 'matrix-js-sdk';
|
import Matrix from 'matrix-js-sdk';
|
||||||
import { _t, _td } from '../../languageHandler';
|
import { _t, _td } from '../../languageHandler';
|
||||||
import * as sdk from '../../index';
|
|
||||||
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../MatrixClientPeg';
|
||||||
import Resend from '../../Resend';
|
import Resend from '../../Resend';
|
||||||
import dis from '../../dispatcher/dispatcher';
|
import dis from '../../dispatcher/dispatcher';
|
||||||
import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils';
|
import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils';
|
||||||
import {Action} from "../../dispatcher/actions";
|
import {Action} from "../../dispatcher/actions";
|
||||||
import { CallState, CallType } from 'matrix-js-sdk/lib/webrtc/call';
|
|
||||||
|
|
||||||
const STATUS_BAR_HIDDEN = 0;
|
const STATUS_BAR_HIDDEN = 0;
|
||||||
const STATUS_BAR_EXPANDED = 1;
|
const STATUS_BAR_EXPANDED = 1;
|
||||||
@ -42,13 +40,6 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
// the room this statusbar is representing.
|
// the room this statusbar is representing.
|
||||||
room: PropTypes.object.isRequired,
|
room: PropTypes.object.isRequired,
|
||||||
|
|
||||||
// The active call in the room, if any (means we show the call bar
|
|
||||||
// along with the status of the call)
|
|
||||||
callState: PropTypes.string,
|
|
||||||
|
|
||||||
// The type of the call in progress, or null if no call is in progress
|
|
||||||
callType: PropTypes.string,
|
|
||||||
|
|
||||||
// true if the room is being peeked at. This affects components that shouldn't
|
// true if the room is being peeked at. This affects components that shouldn't
|
||||||
// logically be shown when peeking, such as a prompt to invite people to a room.
|
// logically be shown when peeking, such as a prompt to invite people to a room.
|
||||||
isPeeking: PropTypes.bool,
|
isPeeking: PropTypes.bool,
|
||||||
@ -115,12 +106,6 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_showCallBar() {
|
|
||||||
return (this.props.callState &&
|
|
||||||
(this.props.callState !== CallState.Ended && this.props.callState !== CallState.Ringing)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onResendAllClick = () => {
|
_onResendAllClick = () => {
|
||||||
Resend.resendUnsentEvents(this.props.room);
|
Resend.resendUnsentEvents(this.props.room);
|
||||||
dis.fire(Action.FocusComposer);
|
dis.fire(Action.FocusComposer);
|
||||||
@ -152,7 +137,7 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
// changed - so we use '0' to indicate normal size, and other values to
|
// changed - so we use '0' to indicate normal size, and other values to
|
||||||
// indicate other sizes.
|
// indicate other sizes.
|
||||||
_getSize() {
|
_getSize() {
|
||||||
if (this._shouldShowConnectionError() || this._showCallBar()) {
|
if (this._shouldShowConnectionError()) {
|
||||||
return STATUS_BAR_EXPANDED;
|
return STATUS_BAR_EXPANDED;
|
||||||
} else if (this.state.unsentMessages.length > 0) {
|
} else if (this.state.unsentMessages.length > 0) {
|
||||||
return STATUS_BAR_EXPANDED_LARGE;
|
return STATUS_BAR_EXPANDED_LARGE;
|
||||||
@ -160,22 +145,6 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
return STATUS_BAR_HIDDEN;
|
return STATUS_BAR_HIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return suitable content for the image on the left of the status bar.
|
|
||||||
_getIndicator() {
|
|
||||||
if (this._showCallBar()) {
|
|
||||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
|
||||||
return (
|
|
||||||
<TintableSvg src={require("../../../res/img/element-icons/room/in-call.svg")} width="23" height="20" />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._shouldShowConnectionError()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_shouldShowConnectionError() {
|
_shouldShowConnectionError() {
|
||||||
// no conn bar trumps the "some not sent" msg since you can't resend without
|
// no conn bar trumps the "some not sent" msg since you can't resend without
|
||||||
// a connection!
|
// a connection!
|
||||||
@ -266,25 +235,6 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCallStatusText() {
|
|
||||||
switch (this.props.callState) {
|
|
||||||
case CallState.CreateOffer:
|
|
||||||
case CallState.InviteSent:
|
|
||||||
return _t('Calling...');
|
|
||||||
case CallState.Connecting:
|
|
||||||
case CallState.CreateAnswer:
|
|
||||||
return _t('Call connecting...');
|
|
||||||
case CallState.Connected:
|
|
||||||
return _t('Active call');
|
|
||||||
case CallState.WaitLocalMedia:
|
|
||||||
if (this.props.callType === CallType.Video) {
|
|
||||||
return _t('Starting camera...');
|
|
||||||
} else {
|
|
||||||
return _t('Starting microphone...');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return suitable content for the main (text) part of the status bar.
|
// return suitable content for the main (text) part of the status bar.
|
||||||
_getContent() {
|
_getContent() {
|
||||||
if (this._shouldShowConnectionError()) {
|
if (this._shouldShowConnectionError()) {
|
||||||
@ -307,26 +257,14 @@ export default class RoomStatusBar extends React.Component {
|
|||||||
return this._getUnsentMessageContent();
|
return this._getUnsentMessageContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._showCallBar()) {
|
|
||||||
return (
|
|
||||||
<div className="mx_RoomStatusBar_callBar">
|
|
||||||
<b>{ this._getCallStatusText() }</b>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const content = this._getContent();
|
const content = this._getContent();
|
||||||
const indicator = this._getIndicator();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomStatusBar">
|
<div className="mx_RoomStatusBar">
|
||||||
<div className="mx_RoomStatusBar_indicator">
|
|
||||||
{ indicator }
|
|
||||||
</div>
|
|
||||||
<div role="alert">
|
<div role="alert">
|
||||||
{ content }
|
{ content }
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@ import rateLimitedFunc from '../../ratelimitedfunc';
|
|||||||
import * as ObjectUtils from '../../ObjectUtils';
|
import * as ObjectUtils from '../../ObjectUtils';
|
||||||
import * as Rooms from '../../Rooms';
|
import * as Rooms from '../../Rooms';
|
||||||
import eventSearch, {searchPagination} from '../../Searching';
|
import eventSearch, {searchPagination} from '../../Searching';
|
||||||
import {isOnlyCtrlOrCmdIgnoreShiftKeyEvent, isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard';
|
import {isOnlyCtrlOrCmdIgnoreShiftKeyEvent, Key} from '../../Keyboard';
|
||||||
import MainSplit from './MainSplit';
|
import MainSplit from './MainSplit';
|
||||||
import RightPanel from './RightPanel';
|
import RightPanel from './RightPanel';
|
||||||
import RoomViewStore from '../../stores/RoomViewStore';
|
import RoomViewStore from '../../stores/RoomViewStore';
|
||||||
@ -68,10 +68,9 @@ import RoomUpgradeWarningBar from "../views/rooms/RoomUpgradeWarningBar";
|
|||||||
import PinnedEventsPanel from "../views/rooms/PinnedEventsPanel";
|
import PinnedEventsPanel from "../views/rooms/PinnedEventsPanel";
|
||||||
import AuxPanel from "../views/rooms/AuxPanel";
|
import AuxPanel from "../views/rooms/AuxPanel";
|
||||||
import RoomHeader from "../views/rooms/RoomHeader";
|
import RoomHeader from "../views/rooms/RoomHeader";
|
||||||
import TintableSvg from "../views/elements/TintableSvg";
|
|
||||||
import {XOR} from "../../@types/common";
|
import {XOR} from "../../@types/common";
|
||||||
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
||||||
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||||
import WidgetStore from "../../stores/WidgetStore";
|
import WidgetStore from "../../stores/WidgetStore";
|
||||||
import {UPDATE_EVENT} from "../../stores/AsyncStore";
|
import {UPDATE_EVENT} from "../../stores/AsyncStore";
|
||||||
import Notifier from "../../Notifier";
|
import Notifier from "../../Notifier";
|
||||||
@ -508,8 +507,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
this.props.resizeNotifier.on("middlePanelResized", this.onResize);
|
this.props.resizeNotifier.on("middlePanelResized", this.onResize);
|
||||||
}
|
}
|
||||||
this.onResize();
|
this.onResize();
|
||||||
|
|
||||||
document.addEventListener("keydown", this.onNativeKeyDown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
@ -592,8 +589,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize);
|
this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.removeEventListener("keydown", this.onNativeKeyDown);
|
|
||||||
|
|
||||||
// Remove RoomStore listener
|
// Remove RoomStore listener
|
||||||
if (this.roomStoreToken) {
|
if (this.roomStoreToken) {
|
||||||
this.roomStoreToken.remove();
|
this.roomStoreToken.remove();
|
||||||
@ -642,33 +637,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// we register global shortcuts here, they *must not conflict* with local shortcuts elsewhere or both will fire
|
|
||||||
private onNativeKeyDown = ev => {
|
|
||||||
let handled = false;
|
|
||||||
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
|
||||||
|
|
||||||
switch (ev.key) {
|
|
||||||
case Key.D:
|
|
||||||
if (ctrlCmdOnly) {
|
|
||||||
this.onMuteAudioClick();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Key.E:
|
|
||||||
if (ctrlCmdOnly) {
|
|
||||||
this.onMuteVideoClick();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handled) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
ev.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private onReactKeyDown = ev => {
|
private onReactKeyDown = ev => {
|
||||||
let handled = false;
|
let handled = false;
|
||||||
|
|
||||||
@ -1758,8 +1726,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
isStatusAreaExpanded = this.state.statusBarVisible;
|
isStatusAreaExpanded = this.state.statusBarVisible;
|
||||||
statusBar = <RoomStatusBar
|
statusBar = <RoomStatusBar
|
||||||
room={this.state.room}
|
room={this.state.room}
|
||||||
callState={this.state.callState}
|
|
||||||
callType={activeCall ? activeCall.type : null}
|
|
||||||
isPeeking={myMembership !== "join"}
|
isPeeking={myMembership !== "join"}
|
||||||
onInviteClick={this.onInviteButtonClick}
|
onInviteClick={this.onInviteButtonClick}
|
||||||
onVisible={this.onStatusBarVisible}
|
onVisible={this.onStatusBarVisible}
|
||||||
@ -1883,56 +1849,6 @@ export default class RoomView extends React.Component<IProps, IState> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeCall) {
|
|
||||||
let zoomButton; let videoMuteButton;
|
|
||||||
|
|
||||||
if (activeCall.type === CallType.Video) {
|
|
||||||
zoomButton = (
|
|
||||||
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title={_t("Fill screen")}>
|
|
||||||
<TintableSvg
|
|
||||||
src={require("../../../res/img/element-icons/call/fullscreen.svg")}
|
|
||||||
width="29"
|
|
||||||
height="22"
|
|
||||||
style={{ marginTop: 1, marginRight: 4 }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
videoMuteButton =
|
|
||||||
<div className="mx_RoomView_voipButton" onClick={this.onMuteVideoClick}>
|
|
||||||
<TintableSvg
|
|
||||||
src={activeCall.isLocalVideoMuted() ?
|
|
||||||
require("../../../res/img/element-icons/call/video-muted.svg") :
|
|
||||||
require("../../../res/img/element-icons/call/video-call.svg")}
|
|
||||||
alt={activeCall.isLocalVideoMuted() ? _t("Click to unmute video") :
|
|
||||||
_t("Click to mute video")}
|
|
||||||
width=""
|
|
||||||
height="27"
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
const voiceMuteButton =
|
|
||||||
<div className="mx_RoomView_voipButton" onClick={this.onMuteAudioClick}>
|
|
||||||
<TintableSvg
|
|
||||||
src={activeCall.isMicrophoneMuted() ?
|
|
||||||
require("../../../res/img/element-icons/call/voice-muted.svg") :
|
|
||||||
require("../../../res/img/element-icons/call/voice-unmuted.svg")}
|
|
||||||
alt={activeCall.isMicrophoneMuted() ? _t("Click to unmute audio") : _t("Click to mute audio")}
|
|
||||||
width="21"
|
|
||||||
height="26"
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
|
|
||||||
// wrap the existing status bar into a 'callStatusBar' which adds more knobs.
|
|
||||||
statusBar =
|
|
||||||
<div className="mx_RoomView_callStatusBar">
|
|
||||||
{ voiceMuteButton }
|
|
||||||
{ videoMuteButton }
|
|
||||||
{ zoomButton }
|
|
||||||
{ statusBar }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have search results, we keep the messagepanel (so that it preserves its
|
// if we have search results, we keep the messagepanel (so that it preserves its
|
||||||
// scroll state), but hide it.
|
// scroll state), but hide it.
|
||||||
let searchResultsPanel;
|
let searchResultsPanel;
|
||||||
|
@ -27,6 +27,7 @@ import { CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
|||||||
import { CallEvent } from 'matrix-js-sdk/src/webrtc/call';
|
import { CallEvent } 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';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// js-sdk room object. If set, we will only show calls for the given
|
// js-sdk room object. If set, we will only show calls for the given
|
||||||
@ -108,9 +109,11 @@ export default class CallView extends React.Component<IProps, IState> {
|
|||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
document.addEventListener('keydown', this.onNativeKeyDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
|
document.removeEventListener("keydown", this.onNativeKeyDown);
|
||||||
this.updateCallListeners(this.state.call, null);
|
this.updateCallListeners(this.state.call, null);
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
}
|
}
|
||||||
@ -198,14 +201,18 @@ export default class CallView extends React.Component<IProps, IState> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onControlsHideTimer = () => {
|
private onControlsHideTimer = () => {
|
||||||
this.controlsHideTimer = null;
|
this.controlsHideTimer = null;
|
||||||
this.setState({
|
this.setState({
|
||||||
controlsVisible: false,
|
controlsVisible: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseMove = () => {
|
private onMouseMove = () => {
|
||||||
|
this.showControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private showControls() {
|
||||||
if (!this.state.controlsVisible) {
|
if (!this.state.controlsVisible) {
|
||||||
this.setState({
|
this.setState({
|
||||||
controlsVisible: true,
|
controlsVisible: true,
|
||||||
@ -217,21 +224,58 @@ export default class CallView extends React.Component<IProps, IState> {
|
|||||||
this.controlsHideTimer = window.setTimeout(this.onControlsHideTimer, CONTROLS_HIDE_DELAY);
|
this.controlsHideTimer = window.setTimeout(this.onControlsHideTimer, CONTROLS_HIDE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMicMuteClick = () => {
|
private onMicMuteClick = () => {
|
||||||
|
if (!this.state.call) return;
|
||||||
|
|
||||||
const newVal = !this.state.micMuted;
|
const newVal = !this.state.micMuted;
|
||||||
|
|
||||||
this.state.call.setMicrophoneMuted(newVal);
|
this.state.call.setMicrophoneMuted(newVal);
|
||||||
this.setState({micMuted: newVal});
|
this.setState({micMuted: newVal});
|
||||||
}
|
}
|
||||||
|
|
||||||
onVidMuteClick = () => {
|
private onVidMuteClick = () => {
|
||||||
|
if (!this.state.call) return;
|
||||||
|
|
||||||
const newVal = !this.state.vidMuted;
|
const newVal = !this.state.vidMuted;
|
||||||
|
|
||||||
this.state.call.setLocalVideoMuted(newVal);
|
this.state.call.setLocalVideoMuted(newVal);
|
||||||
this.setState({vidMuted: newVal});
|
this.setState({vidMuted: newVal});
|
||||||
}
|
}
|
||||||
|
|
||||||
onRoomAvatarClick = () => {
|
// we register global shortcuts here, they *must not conflict* with local shortcuts elsewhere or both will fire
|
||||||
|
// Note that this assumes we always have a callview on screen at any given time
|
||||||
|
// CallHandler would probably be a better place for this
|
||||||
|
private onNativeKeyDown = ev => {
|
||||||
|
let handled = false;
|
||||||
|
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||||
|
|
||||||
|
switch (ev.key) {
|
||||||
|
case Key.D:
|
||||||
|
if (ctrlCmdOnly) {
|
||||||
|
this.onMicMuteClick();
|
||||||
|
// show the controls to give feedback
|
||||||
|
this.showControls();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key.E:
|
||||||
|
if (ctrlCmdOnly) {
|
||||||
|
this.onVidMuteClick();
|
||||||
|
// show the controls to give feedback
|
||||||
|
this.showControls();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handled) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onRoomAvatarClick = () => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
room_id: this.state.call.roomId,
|
room_id: this.state.call.roomId,
|
||||||
@ -279,6 +323,11 @@ export default class CallView extends React.Component<IProps, IState> {
|
|||||||
mx_CallView_callControls_hidden: !this.state.controlsVisible,
|
mx_CallView_callControls_hidden: !this.state.controlsVisible,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const vidMuteButton = this.state.call.type === CallType.Video ? <div
|
||||||
|
className={vidClasses}
|
||||||
|
onClick={this.onVidMuteClick}
|
||||||
|
/> : null;
|
||||||
|
|
||||||
callControls = <div className={callControlsClasses}>
|
callControls = <div className={callControlsClasses}>
|
||||||
<div
|
<div
|
||||||
className={micClasses}
|
className={micClasses}
|
||||||
@ -293,18 +342,9 @@ export default class CallView extends React.Component<IProps, IState> {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div
|
{vidMuteButton}
|
||||||
className={vidClasses}
|
<div className={micCacheClasses} />
|
||||||
onClick={this.onVidMuteClick}
|
<div className={vidCacheClasses} />
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={micCacheClasses}
|
|
||||||
onClick={this.onMicMuteClick}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={vidCacheClasses}
|
|
||||||
onClick={this.onMicMuteClick}
|
|
||||||
/>
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user