From 2a02e57a953154dc15f0fd14f0321d95e3bcb3c9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 26 Nov 2020 14:35:09 +0000 Subject: [PATCH 01/10] Add UI for hold functionality --- res/css/_components.scss | 1 + .../views/context_menus/_CallContextMenu.scss | 23 +++ res/css/views/voip/_CallView.scss | 100 ++++++++++++ src/components/structures/ContextMenu.tsx | 6 +- .../views/context_menus/CallContextMenu.tsx | 51 ++++++ src/components/views/voip/CallView.tsx | 152 ++++++++++++++++-- src/i18n/strings/en_EN.json | 4 + 7 files changed, 320 insertions(+), 17 deletions(-) create mode 100644 res/css/views/context_menus/_CallContextMenu.scss create mode 100644 src/components/views/context_menus/CallContextMenu.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 445ed70ff4..414e2dc6a6 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -53,6 +53,7 @@ @import "./views/avatars/_MemberStatusMessageAvatar.scss"; @import "./views/avatars/_PulsedAvatar.scss"; @import "./views/avatars/_WidgetAvatar.scss"; +@import "./views/context_menus/_CallContextMenu.scss"; @import "./views/context_menus/_IconizedContextMenu.scss"; @import "./views/context_menus/_MessageContextMenu.scss"; @import "./views/context_menus/_StatusMessageContextMenu.scss"; diff --git a/res/css/views/context_menus/_CallContextMenu.scss b/res/css/views/context_menus/_CallContextMenu.scss new file mode 100644 index 0000000000..55b73b0344 --- /dev/null +++ b/res/css/views/context_menus/_CallContextMenu.scss @@ -0,0 +1,23 @@ +/* +Copyright 2020 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_CallContextMenu_item { + width: 205px; + height: 40px; + padding-left: 16px; + line-height: 40px; + vertical-align: center; +} diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 2b87181b1e..d5e58c94c5 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -43,17 +43,99 @@ limitations under the License. .mx_CallView_voice { position: relative; display: flex; + flex-direction: column; align-items: center; justify-content: center; background-color: $inverted-bg-color; } +.mx_CallView_voice_hold { + // This masks the avatar image so when it's blurred, the edge is still crisp + .mx_CallView_voice_avatarContainer { + border-radius: 2000px; + overflow: hidden; + position: relative; + &::after { + position: absolute; + content: ''; + width: 20px; + height: 20px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-image: url('$(res)/img/voip/paused.svg'); + background-position: center; + background-size: cover; + } + } + .mx_BaseAvatar { + filter: blur(20px); + overflow: hidden; + } +} + +.mx_CallView_voice_holdText { + height: 16px; + color: $accent-fg-color; + .mx_AccessibleButton_hasKind { + padding: 0px; + } +} + .mx_CallView_video { width: 100%; position: relative; z-index: 30; } +.mx_CallView_video_hold { + overflow: hidden; + + // we keep these around in the DOM: it saved wiring them up again when the call + // is resumed and keeps the container the right size + .mx_VideoFeed { + visibility: hidden; + } +} + +.mx_CallView_video_holdBackground { + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + filter: blur(20px); +} + +.mx_CallView_video_holdContent { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-weight: bold; + color: $accent-fg-color; + text-align: center; + + &::before { + display: block; + margin-left: auto; + margin-right: auto; + content: ''; + width: 20px; + height: 20px; + background-image: url('$(res)/img/voip/paused.svg'); + background-position: center; + background-size: cover; + } + .mx_AccessibleButton_hasKind { + display: block; + padding: 0px; + } +} + .mx_CallView_header { height: 44px; display: flex; @@ -173,6 +255,12 @@ limitations under the License. } } +// Makes the alignment correct +.mx_CallView_callControls_nothing { + margin-right: auto; + cursor: initial; +} + .mx_CallView_callControls_button_micOn { &::before { background-image: url('$(res)/img/voip/mic-on.svg'); @@ -203,6 +291,18 @@ limitations under the License. } } +.mx_CallView_callControls_button_more { + margin-left: auto; + &::before { + background-image: url('$(res)/img/voip/more.svg'); + } +} + +.mx_CallView_callControls_button_more_hidden { + margin-left: auto; + cursor: initial; +} + .mx_CallView_callControls_button_invisible { visibility: hidden; pointer-events: none; diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index fa0d6682dd..190b231b74 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -398,7 +398,7 @@ export const toRightOf = (elementRect: DOMRect, chevronOffset = 12) => { }; // Placement method for to position context menu right-aligned and flowing to the left of elementRect -export const aboveLeftOf = (elementRect: DOMRect, chevronFace = ChevronFace.None) => { +export const aboveLeftOf = (elementRect: DOMRect, chevronFace = ChevronFace.None, vPadding = 0) => { const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace }; const buttonRight = elementRect.right + window.pageXOffset; @@ -408,9 +408,9 @@ export const aboveLeftOf = (elementRect: DOMRect, chevronFace = ChevronFace.None menuOptions.right = window.innerWidth - buttonRight; // Align the menu vertically on whichever side of the button has more space available. if (buttonBottom < window.innerHeight / 2) { - menuOptions.top = buttonBottom; + menuOptions.top = buttonBottom + vPadding; } else { - menuOptions.bottom = window.innerHeight - buttonTop; + menuOptions.bottom = (window.innerHeight - buttonTop) + vPadding; } return menuOptions; diff --git a/src/components/views/context_menus/CallContextMenu.tsx b/src/components/views/context_menus/CallContextMenu.tsx new file mode 100644 index 0000000000..31e82c19b1 --- /dev/null +++ b/src/components/views/context_menus/CallContextMenu.tsx @@ -0,0 +1,51 @@ +/* +Copyright 2020 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { _t } from '../../../languageHandler'; +import { ContextMenu, IProps as IContextMenuProps, MenuItem } from '../../structures/ContextMenu'; +import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; + +interface IProps extends IContextMenuProps { + call: MatrixCall; +} + +export default class CallContextMenu extends React.Component { + static propTypes = { + // js-sdk User object. Not required because it might not exist. + user: PropTypes.object, + }; + + constructor(props) { + super(props); + } + + onHoldUnholdClick = () => { + this.props.call.setRemoteOnHold(!this.props.call.isRemoteOnHold()); + this.props.onFinished(); + } + + render() { + const holdUnholdCaption = this.props.call.isRemoteOnHold() ? _t("Resume") : _t("Hold"); + + return + + {holdUnholdCaption} + + ; + } +} diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index db6d2b7ae0..c9f5db77e6 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { createRef } from 'react'; +import React, { createRef, CSSProperties } from 'react'; import Room from 'matrix-js-sdk/src/models/room'; import dis from '../../../dispatcher/dispatcher'; import CallHandler from '../../../CallHandler'; @@ -28,6 +28,9 @@ import { CallEvent } from 'matrix-js-sdk/src/webrtc/call'; import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; +import {aboveLeftOf, ChevronFace, ContextMenuButton} from '../../structures/ContextMenu'; +import CallContextMenu from '../context_menus/CallContextMenu'; +import { avatarUrlForMember } from '../../../Avatar'; interface IProps { // js-sdk room object. If set, we will only show calls for the given @@ -51,10 +54,12 @@ interface IProps { interface IState { call: MatrixCall; isLocalOnHold: boolean, + isRemoteOnHold: boolean, micMuted: boolean, vidMuted: boolean, callState: CallState, controlsVisible: boolean, + showMoreMenu: boolean, } function getFullScreenElement() { @@ -89,11 +94,14 @@ const CONTROLS_HIDE_DELAY = 1000; // Height of the header duplicated from CSS because we need to subtract it from our max // height to get the max height of the video const HEADER_HEIGHT = 44; +const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the button (px) export default class CallView extends React.Component { private dispatcherRef: string; private contentRef = createRef(); private controlsHideTimer: number = null; + private contextMenuButton = createRef(); + constructor(props: IProps) { super(props); @@ -101,10 +109,12 @@ export default class CallView extends React.Component { this.state = { call, isLocalOnHold: call ? call.isLocalOnHold() : null, + isRemoteOnHold: call ? call.isRemoteOnHold() : null, micMuted: call ? call.isMicrophoneMuted() : null, vidMuted: call ? call.isLocalVideoMuted() : null, callState: call ? call.state : null, controlsVisible: true, + showMoreMenu: false, } this.updateCallListeners(null, call); @@ -149,11 +159,16 @@ export default class CallView extends React.Component { this.setState({ call: newCall, isLocalOnHold: newCall ? newCall.isLocalOnHold() : null, + isRemoteOnHold: newCall ? newCall.isRemoteOnHold() : null, micMuted: newCall ? newCall.isMicrophoneMuted() : null, vidMuted: newCall ? newCall.isLocalVideoMuted() : null, callState: newCall ? newCall.state : null, controlsVisible: newControlsVisible, }); + } else { + this.setState({ + callState: newCall ? newCall.state : null, + }); } if (!newCall && getFullScreenElement()) { exitFullscreen(); @@ -187,16 +202,30 @@ export default class CallView extends React.Component { private updateCallListeners(oldCall: MatrixCall, newCall: MatrixCall) { if (oldCall === newCall) return; - if (oldCall) oldCall.removeListener(CallEvent.HoldUnhold, this.onCallHoldUnhold); - if (newCall) newCall.on(CallEvent.HoldUnhold, this.onCallHoldUnhold); + if (oldCall) { + oldCall.removeListener(CallEvent.LocalHoldUnhold, this.onCallLocalHoldUnhold); + oldCall.removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHoldUnhold); + } + if (newCall) { + newCall.on(CallEvent.LocalHoldUnhold, this.onCallLocalHoldUnhold); + newCall.on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHoldUnhold); + } } - private onCallHoldUnhold = () => { + private onCallLocalHoldUnhold = () => { this.setState({ isLocalOnHold: this.state.call ? this.state.call.isLocalOnHold() : null, }); }; + private onCallRemoteHoldUnhold = () => { + this.setState({ + isRemoteOnHold: this.state.call ? this.state.call.isRemoteOnHold() : null, + // update both here because isLocalOnHold changes when we hold the call too + isLocalOnHold: this.state.call ? this.state.call.isLocalOnHold() : null, + }); + }; + private onFullscreenClick = () => { dis.dispatch({ action: 'video_fullscreen', @@ -223,6 +252,8 @@ export default class CallView extends React.Component { } private showControls() { + if (this.state.showMoreMenu) return; + if (!this.state.controlsVisible) { this.setState({ controlsVisible: true, @@ -252,6 +283,25 @@ export default class CallView extends React.Component { this.setState({vidMuted: newVal}); } + private onMoreClick = () => { + if (this.controlsHideTimer) { + clearTimeout(this.controlsHideTimer); + this.controlsHideTimer = null; + } + + this.setState({ + showMoreMenu: true, + controlsVisible: true, + }); + } + + private closeContextMenu = () => { + this.setState({ + showMoreMenu: false, + }); + this.controlsHideTimer = window.setTimeout(this.onControlsHideTimer, CONTROLS_HIDE_DELAY); + } + // 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 @@ -292,14 +342,32 @@ export default class CallView extends React.Component { }); } + private onCallResumeClick = () => { + this.state.call.setRemoteOnHold(false); + } + public render() { if (!this.state.call) return null; const client = MatrixClientPeg.get(); const callRoom = client.getRoom(this.state.call.roomId); + let contextMenu; + let callControls; if (this.props.room) { + if (this.state.showMoreMenu) { + contextMenu = ; + } + const micClasses = classNames({ mx_CallView_callControls_button: true, mx_CallView_callControls_button_micOn: !this.state.micMuted, @@ -333,17 +401,29 @@ export default class CallView extends React.Component { mx_CallView_callControls_hidden: !this.state.controlsVisible, }); - const vidMuteButton = this.state.call.type === CallType.Video ?
: null; + // The 'more' button actions are only relevant in a connected call + // When not connected, we have to put something there to make the flexbox alignment correct + const contextMenuButton = this.state.callState === CallState.Connected ? :
; + + // in the near future, the dial pad button will go on the left. For now, it's the nothing button + // because something needs to have margin-right: auto to make the alignment correct. callControls =
-
+ -
{ dis.dispatch({ @@ -355,6 +435,7 @@ export default class CallView extends React.Component { {vidMuteButton}
+ {contextMenuButton}
; } @@ -362,24 +443,66 @@ export default class CallView extends React.Component { // for voice calls (fills the bg) let contentView: React.ReactNode; + const isOnHold = this.state.isLocalOnHold || this.state.isRemoteOnHold; + let onHoldText = null; + if (this.state.isRemoteOnHold) { + onHoldText = _t("You held the call Resume", {}, { + a: sub => + {sub} + , + }); + } else if (this.state.isLocalOnHold) { + onHoldText = _t("%(peerName)s held the call", { + peerName: this.state.call.getOpponentMember().name, + }); + } + if (this.state.call.type === CallType.Video) { + let onHoldContent = null; + let onHoldBackground = null; + const backgroundStyle: CSSProperties = {}; + const containerClasses = classNames({ + mx_CallView_video: true, + mx_CallView_video_hold: isOnHold, + }); + if (isOnHold) { + onHoldContent =
+ {onHoldText} +
; + const backgroundAvatarUrl = avatarUrlForMember( + // is it worth getting the size of the div to pass here? + this.state.call.getOpponentMember(), 1024, 1024, 'crop', + ); + backgroundStyle.backgroundImage = 'url(' + backgroundAvatarUrl + ')'; + onHoldBackground =
; + } + // if we're fullscreen, we don't want to set a maxHeight on the video element. const maxVideoHeight = getFullScreenElement() ? null : this.props.maxVideoHeight - HEADER_HEIGHT; - contentView =
+ contentView =
+ {onHoldBackground} + {onHoldContent} {callControls}
; } else { const avatarSize = this.props.room ? 200 : 75; - contentView =
- + const classes = classNames({ + mx_CallView_voice: true, + mx_CallView_voice_hold: isOnHold, + }); + contentView =
+
+ +
+
{onHoldText}
{callControls}
; } @@ -431,6 +554,7 @@ export default class CallView extends React.Component { return
{header} {contentView} + {contextMenu}
; } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0d50128f32..de1c20be1b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -836,6 +836,8 @@ "When rooms are upgraded": "When rooms are upgraded", "My Ban List": "My Ban List", "This is your list of users/servers you have blocked - don't leave the room!": "This is your list of users/servers you have blocked - don't leave the room!", + "You held the call Resume": "You held the call Resume", + "%(peerName)s held the call": "%(peerName)s held the call", "Video Call": "Video Call", "Voice Call": "Voice Call", "Fill Screen": "Fill Screen", @@ -2231,6 +2233,8 @@ "Warning: You should only set up key backup from a trusted computer.": "Warning: You should only set up key backup from a trusted computer.", "Access your secure message history and set up secure messaging by entering your recovery key.": "Access your secure message history and set up secure messaging by entering your recovery key.", "If you've forgotten your recovery key you can ": "If you've forgotten your recovery key you can ", + "Resume": "Resume", + "Hold": "Hold", "Reject invitation": "Reject invitation", "Are you sure you want to reject the invitation?": "Are you sure you want to reject the invitation?", "Unable to reject invite": "Unable to reject invite", From 5b7ad079d2471051f7d5c921ed0f76b0149ead5f Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 26 Nov 2020 14:55:07 +0000 Subject: [PATCH 02/10] Add SVGs --- res/img/voip/more.svg | 17 +++++++++++++++++ res/img/voip/paused.svg | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 res/img/voip/more.svg create mode 100644 res/img/voip/paused.svg diff --git a/res/img/voip/more.svg b/res/img/voip/more.svg new file mode 100644 index 0000000000..7990f6bcff --- /dev/null +++ b/res/img/voip/more.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/res/img/voip/paused.svg b/res/img/voip/paused.svg new file mode 100644 index 0000000000..a967bf8ddf --- /dev/null +++ b/res/img/voip/paused.svg @@ -0,0 +1,3 @@ + + + From 4ca35fabefe5ada2edcc631f9f6ec84b12b2e30b Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 1 Dec 2020 13:44:24 +0000 Subject: [PATCH 03/10] Visual tweaks --- res/css/views/voip/_CallView.scss | 21 +++++++++++++++------ src/CallHandler.tsx | 14 ++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index d5e58c94c5..57806470a1 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -58,8 +58,8 @@ limitations under the License. &::after { position: absolute; content: ''; - width: 20px; - height: 20px; + width: 40px; + height: 40px; top: 50%; left: 50%; transform: translate(-50%, -50%); @@ -67,6 +67,10 @@ limitations under the License. background-position: center; background-size: cover; } + .mx_CallView_pip &::after { + width: 30px; + height: 30px; + } } .mx_BaseAvatar { filter: blur(20px); @@ -75,8 +79,10 @@ limitations under the License. } .mx_CallView_voice_holdText { - height: 16px; + height: 20px; + padding-top: 10px; color: $accent-fg-color; + font-weight: bold; .mx_AccessibleButton_hasKind { padding: 0px; } @@ -124,14 +130,17 @@ limitations under the License. margin-left: auto; margin-right: auto; content: ''; - width: 20px; - height: 20px; + width: 40px; + height: 40px; background-image: url('$(res)/img/voip/paused.svg'); background-position: center; background-size: cover; } + .mx_CallView_pip &::before { + width: 30px; + height: 30px; + } .mx_AccessibleButton_hasKind { - display: block; padding: 0px; } } diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 3be203ab98..544eb0851d 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -477,20 +477,18 @@ export default class CallHandler { break; case 'incoming_call': { - if (this.getAnyActiveCall()) { - // ignore multiple incoming calls. in future, we may want a line-1/line-2 setup. - // we avoid rejecting with "busy" in case the user wants to answer it on a different device. - // in future we could signal a "local busy" as a warning to the caller. - // see https://github.com/vector-im/vector-web/issues/1964 - return; - } - // if the runtime env doesn't do VoIP, stop here. if (!MatrixClientPeg.get().supportsVoip()) { return; } const call = payload.call as MatrixCall; + + if (this.getCallForRoom(call.roomId)) { + // ignore multiple incoming calls to the same room + return; + } + Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); this.calls.set(call.roomId, call) this.setCallListeners(call); From d3b1ec0648f3f5db4bc3b6f494ba70c0a2bb6904 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 1 Dec 2020 15:08:59 +0000 Subject: [PATCH 04/10] Revert unintentional part of 4ca35fabefe5ada2edcc631f9f6ec84b12b2e30b --- src/CallHandler.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 544eb0851d..3be203ab98 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -477,18 +477,20 @@ export default class CallHandler { break; case 'incoming_call': { + if (this.getAnyActiveCall()) { + // ignore multiple incoming calls. in future, we may want a line-1/line-2 setup. + // we avoid rejecting with "busy" in case the user wants to answer it on a different device. + // in future we could signal a "local busy" as a warning to the caller. + // see https://github.com/vector-im/vector-web/issues/1964 + return; + } + // if the runtime env doesn't do VoIP, stop here. if (!MatrixClientPeg.get().supportsVoip()) { return; } const call = payload.call as MatrixCall; - - if (this.getCallForRoom(call.roomId)) { - // ignore multiple incoming calls to the same room - return; - } - Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); this.calls.set(call.roomId, call) this.setCallListeners(call); From c7f1d97b1afe9b5c72a9d84e3a40b1d078ee892e Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 7 Dec 2020 15:38:55 +0000 Subject: [PATCH 06/10] Round off the sharp corners Before you have someone's eye out --- res/css/views/voip/_CallView.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 72c25ef4b3..37f583c437 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -16,7 +16,7 @@ limitations under the License. */ .mx_CallView { - border-radius: 10px; + border-radius: 8px; background-color: $voipcall-plinth-color; padding-left: 8px; padding-right: 8px; @@ -47,6 +47,7 @@ limitations under the License. align-items: center; justify-content: center; background-color: $inverted-bg-color; + border-radius: 8px; } .mx_CallView_voice_hold { @@ -92,6 +93,8 @@ limitations under the License. width: 100%; position: relative; z-index: 30; + border-radius: 8px; + overflow: hidden; } .mx_CallView_video_hold { From 3b25a3be98c7ecb73d481b34573b235ff35e6b7b Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 7 Dec 2020 15:42:35 +0000 Subject: [PATCH 07/10] Smaller avatar, more padding on text --- res/css/views/voip/_CallView.scss | 2 +- src/components/views/voip/CallView.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 37f583c437..d3fc11b63c 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -81,7 +81,7 @@ limitations under the License. .mx_CallView_voice_holdText { height: 20px; - padding-top: 10px; + padding-top: 20px; color: $accent-fg-color; font-weight: bold; .mx_AccessibleButton_hasKind { diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index c9f5db77e6..cfc4a2a16c 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -489,7 +489,7 @@ export default class CallView extends React.Component { {callControls}
; } else { - const avatarSize = this.props.room ? 200 : 75; + const avatarSize = this.props.room ? 160 : 75; const classes = classNames({ mx_CallView_voice: true, mx_CallView_voice_hold: isOnHold, From 747d743bd0cf61ca0b36c2ad2e8fa415692f6154 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 7 Dec 2020 16:22:57 +0000 Subject: [PATCH 08/10] Add 60% opacity black over the avatars when on hold --- res/css/views/voip/_CallView.scss | 21 ++++++++++++++++----- src/components/views/voip/CallView.tsx | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index d3fc11b63c..898318f71d 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -59,18 +59,19 @@ limitations under the License. &::after { position: absolute; content: ''; - width: 40px; - height: 40px; + width: 100%; + height: 100%; top: 50%; left: 50%; transform: translate(-50%, -50%); + background-color: rgba(0, 0, 0, 0.6); background-image: url('$(res)/img/voip/paused.svg'); background-position: center; - background-size: cover; + background-size: 40px; + background-repeat: no-repeat; } .mx_CallView_pip &::after { - width: 30px; - height: 30px; + background-size: 30px; } } .mx_BaseAvatar { @@ -117,6 +118,16 @@ limitations under the License. background-size: cover; background-position: center; filter: blur(20px); + &::after { + content: ''; + display: block; + position: absolute; + width: 100%; + height: 100%; + left: 0; + right: 0; + background-color: rgba(0, 0, 0, 0.6); + } } .mx_CallView_video_holdContent { diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index cfc4a2a16c..078ba18d02 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -489,7 +489,7 @@ export default class CallView extends React.Component { {callControls}
; } else { - const avatarSize = this.props.room ? 160 : 75; + const avatarSize = this.props.room ? 160 : 76; const classes = classNames({ mx_CallView_voice: true, mx_CallView_voice_hold: isOnHold, From 70964e43f6f45998d90b31ab06a254bcfd6f0850 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 8 Dec 2020 19:05:58 +0000 Subject: [PATCH 09/10] Fix font weights in hold text --- res/css/views/voip/_CallView.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 898318f71d..ffe8d95f09 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -84,9 +84,9 @@ limitations under the License. height: 20px; padding-top: 20px; color: $accent-fg-color; - font-weight: bold; .mx_AccessibleButton_hasKind { padding: 0px; + font-weight: bold; } } From 8f24656603602655e6f06084c4a79cd6f258b25c Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 8 Dec 2020 19:26:57 +0000 Subject: [PATCH 10/10] Make margins & header font match widgets --- res/css/views/voip/_CallView.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index ffe8d95f09..f74512ea21 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -20,6 +20,7 @@ limitations under the License. background-color: $voipcall-plinth-color; padding-left: 8px; padding-right: 8px; + margin: 5px 5px 5px 18px; // XXX: CallContainer sets pointer-events: none - should probably be set back in a better place pointer-events: initial; } @@ -172,6 +173,7 @@ limitations under the License. } .mx_CallView_header_callType { + font-size: 1.2rem; font-weight: bold; vertical-align: middle; }