diff --git a/res/css/views/voip/CallView/_CallViewButtons.scss b/res/css/views/voip/CallView/_CallViewButtons.scss index d9396ac3eec..b046ddf40aa 100644 --- a/res/css/views/voip/CallView/_CallViewButtons.scss +++ b/res/css/views/voip/CallView/_CallViewButtons.scss @@ -20,10 +20,11 @@ limitations under the License. position: absolute; display: flex; justify-content: center; - bottom: 5px; + bottom: 24px; opacity: 1; transition: opacity 0.5s; z-index: 200; // To be above _all_ feeds + gap: 18px; &.mx_CallViewButtons_hidden { opacity: 0.001; // opacity 0 can cause a re-layout @@ -32,69 +33,121 @@ limitations under the License. .mx_CallViewButtons_button { cursor: pointer; - margin-left: 2px; - margin-right: 2px; + + background-color: $call-view-button-on-background; + + border-radius: 100%; + height: 40px; + width: 40px; + + display: flex; + justify-content: center; + align-items: center; &::before { content: ''; display: inline-block; - height: 48px; - width: 48px; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; - background-repeat: no-repeat; - background-size: contain; - background-position: center; - } + background-color: $call-view-button-on-foreground; - &.mx_CallViewButtons_dialpad::before { - background-image: url('$(res)/img/voip/dialpad.svg'); + height: 24px; + width: 24px; } - &.mx_CallViewButtons_button_micOn::before { - background-image: url('$(res)/img/voip/mic-on.svg'); - } + // State buttons + &.mx_CallViewButtons_button_on { + background-color: $call-view-button-on-background; - &.mx_CallViewButtons_button_micOff::before { - background-image: url('$(res)/img/voip/mic-off.svg'); - } + &::before { + background-color: $call-view-button-on-foreground; + } - &.mx_CallViewButtons_button_vidOn::before { - background-image: url('$(res)/img/voip/vid-on.svg'); - } + &.mx_CallViewButtons_button_mic::before { + mask-image: url('$(res)/img/voip/call-view/mic-on.svg'); + } - &.mx_CallViewButtons_button_vidOff::before { - background-image: url('$(res)/img/voip/vid-off.svg'); - } + &.mx_CallViewButtons_button_vid::before { + mask-image: url('$(res)/img/voip/call-view/cam-on.svg'); + } - &.mx_CallViewButtons_button_screensharingOn::before { - background-image: url('$(res)/img/voip/screensharing-on.svg'); - } + &.mx_CallViewButtons_button_screensharing { + background-color: $accent; - &.mx_CallViewButtons_button_screensharingOff::before { - background-image: url('$(res)/img/voip/screensharing-off.svg'); + &::before { + mask-image: url('$(res)/img/voip/call-view/screensharing.svg'); + background-color: white; // Same on both themes + } + } + + &.mx_CallViewButtons_button_sidebar::before { + mask-image: url('$(res)/img/voip/call-view/sidebar-on.svg'); + } } - &.mx_CallViewButtons_button_sidebarOn::before { - background-image: url('$(res)/img/voip/sidebar-on.svg'); + &.mx_CallViewButtons_button_off { + background-color: $call-view-button-off-background; + + &::before { + background-color: $call-view-button-off-foreground; + } + + &.mx_CallViewButtons_button_mic::before { + mask-image: url('$(res)/img/voip/call-view/mic-off.svg'); + } + + &.mx_CallViewButtons_button_vid::before { + mask-image: url('$(res)/img/voip/call-view/cam-off.svg'); + } + + &.mx_CallViewButtons_button_screensharing { + background-color: $call-view-button-on-background; + + &::before { + mask-image: url('$(res)/img/voip/call-view/screensharing.svg'); + background-color: $call-view-button-on-foreground; + } + } + + &.mx_CallViewButtons_button_sidebar { + background-color: $call-view-button-on-background; + + &::before { + mask-image: url('$(res)/img/voip/call-view/sidebar-off.svg'); + background-color: $call-view-button-on-foreground; + } + } } + // State buttons - &.mx_CallViewButtons_button_sidebarOff::before { - background-image: url('$(res)/img/voip/sidebar-off.svg'); + // Stateless buttons + &.mx_CallViewButtons_dialpad::before { + mask-image: url('$(res)/img/voip/call-view/dialpad.svg'); } - &.mx_CallViewButtons_button_hangup::before { - background-image: url('$(res)/img/voip/hangup.svg'); + &.mx_CallViewButtons_button_hangup { + background-color: $alert; + + &::before { + mask-image: url('$(res)/img/voip/call-view/hangup.svg'); + background-color: white; // Same on both themes + } } &.mx_CallViewButtons_button_more::before { - background-image: url('$(res)/img/voip/more.svg'); + mask-image: url('$(res)/img/voip/call-view/more.svg'); } + // Stateless buttons + // Invisible state &.mx_CallViewButtons_button_invisible { visibility: hidden; pointer-events: none; position: absolute; } + // Invisible state } } diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 088486bdf6c..5a58711fa53 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -49,13 +49,16 @@ limitations under the License. } .mx_CallViewButtons { - bottom: 0px; + bottom: 13px; } .mx_CallViewButtons_button { + width: 34px; + height: 34px; + &::before { - width: 36px; - height: 36px; + width: 22px; + height: 22px; } } @@ -74,7 +77,6 @@ limitations under the License. > .mx_VideoFeed { width: 100%; height: 100%; - border-width: 0 !important; // Override mx_VideoFeed_speaking &.mx_VideoFeed_voice { display: flex; diff --git a/res/css/views/voip/_CallViewSidebar.scss b/res/css/views/voip/_CallViewSidebar.scss index fd9c76defcb..4871ccfe65e 100644 --- a/res/css/views/voip/_CallViewSidebar.scss +++ b/res/css/views/voip/_CallViewSidebar.scss @@ -39,6 +39,8 @@ limitations under the License. display: flex; align-items: center; justify-content: center; + + background-color: $video-feed-secondary-background; } .mx_VideoFeed_video { diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 1d3c3e1d502..29dcb5cba3c 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -26,14 +26,6 @@ limitations under the License. aspect-ratio: 16 / 9; } - &.mx_VideoFeed_speaking { - border: $accent 2px solid; - - .mx_VideoFeed_video { - border-radius: 0; - } - } - .mx_VideoFeed_video { width: 100%; background-color: transparent; diff --git a/res/img/voip/call-view/cam-off.svg b/res/img/voip/call-view/cam-off.svg new file mode 100644 index 00000000000..9a362905210 --- /dev/null +++ b/res/img/voip/call-view/cam-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/cam-on.svg b/res/img/voip/call-view/cam-on.svg new file mode 100644 index 00000000000..fb18058786f --- /dev/null +++ b/res/img/voip/call-view/cam-on.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/dialpad.svg b/res/img/voip/call-view/dialpad.svg new file mode 100644 index 00000000000..68f1c71b6dc --- /dev/null +++ b/res/img/voip/call-view/dialpad.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/hangup.svg b/res/img/voip/call-view/hangup.svg new file mode 100644 index 00000000000..255433abdc5 --- /dev/null +++ b/res/img/voip/call-view/hangup.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/mic-off.svg b/res/img/voip/call-view/mic-off.svg new file mode 100644 index 00000000000..74d821e6256 --- /dev/null +++ b/res/img/voip/call-view/mic-off.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/mic-on.svg b/res/img/voip/call-view/mic-on.svg new file mode 100644 index 00000000000..57428a3cd8d --- /dev/null +++ b/res/img/voip/call-view/mic-on.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/more.svg b/res/img/voip/call-view/more.svg new file mode 100644 index 00000000000..af15cf16304 --- /dev/null +++ b/res/img/voip/call-view/more.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/screensharing.svg b/res/img/voip/call-view/screensharing.svg new file mode 100644 index 00000000000..4639c34cbfb --- /dev/null +++ b/res/img/voip/call-view/screensharing.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/voip/call-view/sidebar-off.svg b/res/img/voip/call-view/sidebar-off.svg new file mode 100644 index 00000000000..86aae6a05a4 --- /dev/null +++ b/res/img/voip/call-view/sidebar-off.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/res/img/voip/call-view/sidebar-on.svg b/res/img/voip/call-view/sidebar-on.svg new file mode 100644 index 00000000000..535b589098b --- /dev/null +++ b/res/img/voip/call-view/sidebar-on.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/res/img/voip/dialpad.svg b/res/img/voip/dialpad.svg deleted file mode 100644 index 79c9ba16122..00000000000 --- a/res/img/voip/dialpad.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/hangup.svg b/res/img/voip/hangup.svg deleted file mode 100644 index dfb20bd519e..00000000000 --- a/res/img/voip/hangup.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/mic-off.svg b/res/img/voip/mic-off.svg deleted file mode 100644 index 6409f1fd073..00000000000 --- a/res/img/voip/mic-off.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/mic-on.svg b/res/img/voip/mic-on.svg deleted file mode 100644 index 3493b3c5818..00000000000 --- a/res/img/voip/mic-on.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/more.svg b/res/img/voip/more.svg deleted file mode 100644 index 7990f6bcff2..00000000000 --- a/res/img/voip/more.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/screensharing-off.svg b/res/img/voip/screensharing-off.svg deleted file mode 100644 index dc19e9892e4..00000000000 --- a/res/img/voip/screensharing-off.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/screensharing-on.svg b/res/img/voip/screensharing-on.svg deleted file mode 100644 index a8e7fe308e4..00000000000 --- a/res/img/voip/screensharing-on.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/sidebar-off.svg b/res/img/voip/sidebar-off.svg deleted file mode 100644 index 7637a9ab559..00000000000 --- a/res/img/voip/sidebar-off.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/sidebar-on.svg b/res/img/voip/sidebar-on.svg deleted file mode 100644 index a625334be4e..00000000000 --- a/res/img/voip/sidebar-on.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/vid-off.svg b/res/img/voip/vid-off.svg deleted file mode 100644 index 199d97ab974..00000000000 --- a/res/img/voip/vid-off.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/res/img/voip/vid-on.svg b/res/img/voip/vid-on.svg deleted file mode 100644 index d8146d01d34..00000000000 --- a/res/img/voip/vid-on.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 6ed249a1382..3716c67db15 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -179,6 +179,16 @@ $eventbubble-bg-hover: #1C2026; $eventbubble-reply-color: #C1C6CD; // ******************** +// VoIP +// ******************** +$call-view-button-on-foreground: $primary-content; +$call-view-button-on-background: $system; +$call-view-button-off-foreground: $system; +$call-view-button-off-background: $primary-content; + +$video-feed-secondary-background: $system; +// ******************** + // One-off colors // ******************** $kbd-border-color: #000000; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 19ab021a789..894b1386950 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -117,7 +117,12 @@ $space-nav: rgba($panel-base, 0.1); // ******************** -$theme-button-bg-color: #e3e8f0; +$call-view-button-on-foreground: $primary-content; +$call-view-button-on-background: $system; +$call-view-button-off-foreground: $system; +$call-view-button-off-background: $primary-content; + +$video-feed-secondary-background: $system; $roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: $roomlist-button-bg-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 07a0400e24b..703cc9a917a 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -176,6 +176,13 @@ $space-nav: rgba($tertiary-content, 0.15); $voipcall-plinth-color: $system; +$call-view-button-on-foreground: $secondary-content; +$call-view-button-on-background: $background; +$call-view-button-off-foreground: $background; +$call-view-button-off-background: $secondary-content; + +$video-feed-secondary-background: #394049; // XXX: Color from dark theme + $username-variant1-color: #368bd6; $username-variant2-color: #ac3ba8; $username-variant3-color: #03b381; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index dea0763f37f..8a884273357 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -259,7 +259,13 @@ $lightbox-background-bg-opacity: 0.95; // VoIP // ******************** $voipcall-plinth-color: $system; -// more colors to come + +$call-view-button-on-foreground: $secondary-content; +$call-view-button-on-background: $background; +$call-view-button-off-foreground: $background; +$call-view-button-off-background: $secondary-content; + +$video-feed-secondary-background: #394049; // XXX: Color from dark theme // ******************** // One-off colors diff --git a/src/components/views/voip/CallView/CallViewButtons.tsx b/src/components/views/voip/CallView/CallViewButtons.tsx index 466311f4212..0b65fc232e6 100644 --- a/src/components/views/voip/CallView/CallViewButtons.tsx +++ b/src/components/views/voip/CallView/CallViewButtons.tsx @@ -39,6 +39,31 @@ const TOOLTIP_Y_OFFSET = -24; const CONTROLS_HIDE_DELAY = 2000; +interface IButtonProps { + state: boolean; + className: string; + onLabel: string; + offLabel: string; + onClick: () => void; +} + +const CallViewToggleButton: React.FC = ({ state: isOn, className, onLabel, offLabel, onClick }) => { + const classes = classNames("mx_CallViewButtons_button", className, { + mx_CallViewButtons_button_on: isOn, + mx_CallViewButtons_button_off: !isOn, + }); + + return ( + + ); +}; + interface IProps { call: MatrixCall; pipMode: boolean; @@ -142,113 +167,10 @@ export default class CallViewButtons extends React.Component { }; public render(): JSX.Element { - const micClasses = classNames("mx_CallViewButtons_button", { - mx_CallViewButtons_button_micOn: !this.props.buttonsState.micMuted, - mx_CallViewButtons_button_micOff: this.props.buttonsState.micMuted, - }); - - const vidClasses = classNames("mx_CallViewButtons_button", { - mx_CallViewButtons_button_vidOn: !this.props.buttonsState.vidMuted, - mx_CallViewButtons_button_vidOff: this.props.buttonsState.vidMuted, - }); - - const screensharingClasses = classNames("mx_CallViewButtons_button", { - mx_CallViewButtons_button_screensharingOn: this.props.buttonsState.screensharing, - mx_CallViewButtons_button_screensharingOff: !this.props.buttonsState.screensharing, - }); - - const sidebarButtonClasses = classNames("mx_CallViewButtons_button", { - mx_CallViewButtons_button_sidebarOn: this.props.buttonsState.sidebarShown, - mx_CallViewButtons_button_sidebarOff: !this.props.buttonsState.sidebarShown, - }); - - // Put the other states of the mic/video icons in the document to make sure they're cached - // (otherwise the icon disappears briefly when toggled) - const micCacheClasses = classNames("mx_CallViewButtons_button", "mx_CallViewButtons_button_invisible", { - mx_CallViewButtons_button_micOn: this.props.buttonsState.micMuted, - mx_CallViewButtons_button_micOff: !this.props.buttonsState.micMuted, - }); - - const vidCacheClasses = classNames("mx_CallViewButtons_button", "mx_CallViewButtons_button_invisible", { - mx_CallViewButtons_button_vidOn: this.props.buttonsState.micMuted, - mx_CallViewButtons_button_vidOff: !this.props.buttonsState.micMuted, - }); - const callControlsClasses = classNames("mx_CallViewButtons", { mx_CallViewButtons_hidden: !this.state.visible, }); - let vidMuteButton; - if (this.props.buttonsVisibility.vidMute) { - vidMuteButton = ( - - ); - } - - let screensharingButton; - if (this.props.buttonsVisibility.screensharing) { - screensharingButton = ( - - ); - } - - let sidebarButton; - if (this.props.buttonsVisibility.sidebar) { - sidebarButton = ( - - ); - } - - let contextMenuButton; - if (this.props.buttonsVisibility.contextMenu) { - contextMenuButton = ( - - ); - } - let dialpadButton; - if (this.props.buttonsVisibility.dialpad) { - dialpadButton = ( - - ); - } - let dialPad; if (this.state.showDialpad) { dialPad = { > { dialPad } { contextMenu } - { dialpadButton } - } + - { vidMuteButton } -
-
- { screensharingButton } - { sidebarButton } - { contextMenuButton } + { this.props.buttonsVisibility.vidMute && } + { this.props.buttonsVisibility.screensharing && } + { this.props.buttonsVisibility.sidebar && } + { this.props.buttonsVisibility.contextMenu && } { this.state = { audioMuted: this.props.feed.isAudioMuted(), videoMuted: this.props.feed.isVideoMuted(), - speaking: false, }; } @@ -106,7 +104,6 @@ export default class VideoFeed extends React.PureComponent { this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); this.props.feed.removeListener(CallFeedEvent.MuteStateChanged, this.onMuteStateChanged); if (this.props.feed.purpose === SDPStreamMetadataPurpose.Usermedia) { - this.props.feed.removeListener(CallFeedEvent.Speaking, this.onSpeaking); this.props.feed.measureVolumeActivity(false); } this.stopMedia(); @@ -115,7 +112,6 @@ export default class VideoFeed extends React.PureComponent { this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); this.props.feed.addListener(CallFeedEvent.MuteStateChanged, this.onMuteStateChanged); if (this.props.feed.purpose === SDPStreamMetadataPurpose.Usermedia) { - this.props.feed.addListener(CallFeedEvent.Speaking, this.onSpeaking); this.props.feed.measureVolumeActivity(true); } this.playMedia(); @@ -172,10 +168,6 @@ export default class VideoFeed extends React.PureComponent { }); }; - private onSpeaking = (speaking: boolean): void => { - this.setState({ speaking }); - }; - private onResize = (e) => { if (this.props.onResize && !this.props.feed.isLocal()) { this.props.onResize(e); @@ -187,7 +179,6 @@ export default class VideoFeed extends React.PureComponent { const wrapperClasses = classnames("mx_VideoFeed", { mx_VideoFeed_voice: this.state.videoMuted, - mx_VideoFeed_speaking: this.state.speaking, }); const micIconClasses = classnames("mx_VideoFeed_mic", { mx_VideoFeed_mic_muted: this.state.audioMuted, @@ -195,7 +186,11 @@ export default class VideoFeed extends React.PureComponent { }); let micIcon; - if (feed.purpose !== SDPStreamMetadataPurpose.Screenshare && !pipMode) { + if ( + feed.purpose !== SDPStreamMetadataPurpose.Screenshare && + !primary && + !pipMode + ) { micIcon = (
); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 1c243b2dd98..ea7a144e53d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -929,16 +929,16 @@ "%(sharerName)s is presenting": "%(sharerName)s is presenting", "Your camera is turned off": "Your camera is turned off", "Your camera is still enabled": "Your camera is still enabled", - "Start the camera": "Start the camera", + "Dialpad": "Dialpad", + "Mute the microphone": "Mute the microphone", + "Unmute the microphone": "Unmute the microphone", "Stop the camera": "Stop the camera", + "Start the camera": "Start 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", "Video Call": "Video Call", "Voice Call": "Voice Call",