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",