diff --git a/res/css/structures/_RoomStatusBar.scss b/res/css/structures/_RoomStatusBar.scss index 2d5359c0eb..5bf2aee3ae 100644 --- a/res/css/structures/_RoomStatusBar.scss +++ b/res/css/structures/_RoomStatusBar.scss @@ -19,57 +19,6 @@ limitations under the License. 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 { width: 52px; margin-top: -1px; @@ -162,11 +111,6 @@ limitations under the License. margin-top: 10px; } - .mx_RoomStatusBar_callBar { - height: 40px; - line-height: $font-40px; - } - .mx_RoomStatusBar_typingBar { height: 40px; line-height: $font-40px; diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index f3f4eb63de..6c41d62548 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -145,6 +145,9 @@ limitations under the License. .mx_CallView_callControls_button { cursor: pointer; + margin-left: 8px; + margin-right: 8px; + &::before { content: ''; @@ -184,9 +187,6 @@ limitations under the License. } .mx_CallView_callControls_button_hangup { - margin-left: 16px; - margin-right: 16px; - &::before { background-image: url('$(res)/img/voip_buttons/hangup.svg'); } diff --git a/res/img/element-icons/room/in-call.svg b/res/img/element-icons/room/in-call.svg deleted file mode 100644 index 0e574faa84..0000000000 --- a/res/img/element-icons/room/in-call.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index e6d2985073..c1c4ad6292 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -18,13 +18,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import Matrix from 'matrix-js-sdk'; import { _t, _td } from '../../languageHandler'; -import * as sdk from '../../index'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import Resend from '../../Resend'; import dis from '../../dispatcher/dispatcher'; import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils'; import {Action} from "../../dispatcher/actions"; -import { CallState, CallType } from 'matrix-js-sdk/lib/webrtc/call'; const STATUS_BAR_HIDDEN = 0; const STATUS_BAR_EXPANDED = 1; @@ -42,13 +40,6 @@ export default class RoomStatusBar extends React.Component { // the room this statusbar is representing. 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 // logically be shown when peeking, such as a prompt to invite people to a room. 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 = () => { Resend.resendUnsentEvents(this.props.room); 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 // indicate other sizes. _getSize() { - if (this._shouldShowConnectionError() || this._showCallBar()) { + if (this._shouldShowConnectionError()) { return STATUS_BAR_EXPANDED; } else if (this.state.unsentMessages.length > 0) { return STATUS_BAR_EXPANDED_LARGE; @@ -160,22 +145,6 @@ export default class RoomStatusBar extends React.Component { 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 ( - - ); - } - - if (this._shouldShowConnectionError()) { - return null; - } - - return null; - } - _shouldShowConnectionError() { // no conn bar trumps the "some not sent" msg since you can't resend without // a connection! @@ -266,25 +235,6 @@ export default class RoomStatusBar extends React.Component { ; } - _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. _getContent() { if (this._shouldShowConnectionError()) { @@ -307,26 +257,14 @@ export default class RoomStatusBar extends React.Component { return this._getUnsentMessageContent(); } - if (this._showCallBar()) { - return ( -
- { this._getCallStatusText() } -
- ); - } - return null; } render() { const content = this._getContent(); - const indicator = this._getIndicator(); return (
-
- { indicator } -
{ content }
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index de7ae347dd..f730b0056a 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -41,7 +41,7 @@ import rateLimitedFunc from '../../ratelimitedfunc'; import * as ObjectUtils from '../../ObjectUtils'; import * as Rooms from '../../Rooms'; import eventSearch, {searchPagination} from '../../Searching'; -import {isOnlyCtrlOrCmdIgnoreShiftKeyEvent, isOnlyCtrlOrCmdKeyEvent, Key} from '../../Keyboard'; +import {isOnlyCtrlOrCmdIgnoreShiftKeyEvent, Key} from '../../Keyboard'; import MainSplit from './MainSplit'; import RightPanel from './RightPanel'; import RoomViewStore from '../../stores/RoomViewStore'; @@ -68,10 +68,9 @@ import RoomUpgradeWarningBar from "../views/rooms/RoomUpgradeWarningBar"; import PinnedEventsPanel from "../views/rooms/PinnedEventsPanel"; import AuxPanel from "../views/rooms/AuxPanel"; import RoomHeader from "../views/rooms/RoomHeader"; -import TintableSvg from "../views/elements/TintableSvg"; import {XOR} from "../../@types/common"; 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 {UPDATE_EVENT} from "../../stores/AsyncStore"; import Notifier from "../../Notifier"; @@ -508,8 +507,6 @@ export default class RoomView extends React.Component { this.props.resizeNotifier.on("middlePanelResized", this.onResize); } this.onResize(); - - document.addEventListener("keydown", this.onNativeKeyDown); } shouldComponentUpdate(nextProps, nextState) { @@ -592,8 +589,6 @@ export default class RoomView extends React.Component { this.props.resizeNotifier.removeListener("middlePanelResized", this.onResize); } - document.removeEventListener("keydown", this.onNativeKeyDown); - // Remove RoomStore listener if (this.roomStoreToken) { this.roomStoreToken.remove(); @@ -642,33 +637,6 @@ export default class RoomView extends React.Component { } }; - // 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 => { let handled = false; @@ -1758,8 +1726,6 @@ export default class RoomView extends React.Component { isStatusAreaExpanded = this.state.statusBarVisible; statusBar = { }; } - if (activeCall) { - let zoomButton; let videoMuteButton; - - if (activeCall.type === CallType.Video) { - zoomButton = ( -
- -
- ); - - videoMuteButton = -
- -
; - } - const voiceMuteButton = -
- -
; - - // wrap the existing status bar into a 'callStatusBar' which adds more knobs. - statusBar = -
- { voiceMuteButton } - { videoMuteButton } - { zoomButton } - { statusBar } -
; - } - // if we have search results, we keep the messagepanel (so that it preserves its // scroll state), but hide it. let searchResultsPanel; diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index fb6a33d2a8..9eacf0415d 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -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 classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; +import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; interface IProps { // 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 { public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + document.addEventListener('keydown', this.onNativeKeyDown); } public componentWillUnmount() { + document.removeEventListener("keydown", this.onNativeKeyDown); this.updateCallListeners(this.state.call, null); dis.unregister(this.dispatcherRef); } @@ -198,14 +201,18 @@ export default class CallView extends React.Component { }); }; - onControlsHideTimer = () => { + private onControlsHideTimer = () => { this.controlsHideTimer = null; this.setState({ controlsVisible: false, }); } - onMouseMove = () => { + private onMouseMove = () => { + this.showControls(); + } + + private showControls() { if (!this.state.controlsVisible) { this.setState({ controlsVisible: true, @@ -217,21 +224,58 @@ export default class CallView extends React.Component { this.controlsHideTimer = window.setTimeout(this.onControlsHideTimer, CONTROLS_HIDE_DELAY); } - onMicMuteClick = () => { + private onMicMuteClick = () => { + if (!this.state.call) return; + const newVal = !this.state.micMuted; this.state.call.setMicrophoneMuted(newVal); this.setState({micMuted: newVal}); } - onVidMuteClick = () => { + private onVidMuteClick = () => { + if (!this.state.call) return; + const newVal = !this.state.vidMuted; this.state.call.setLocalVideoMuted(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({ action: 'view_room', room_id: this.state.call.roomId, @@ -279,6 +323,11 @@ export default class CallView extends React.Component { mx_CallView_callControls_hidden: !this.state.controlsVisible, }); + const vidMuteButton = this.state.call.type === CallType.Video ?
: null; + callControls =
{ }); }} /> -
-
-
+ {vidMuteButton} +
+
; }