WIP: the new call views work now

just need to add the buttons and then get rid of the status bar
pull/21833/head
David Baker 2020-11-12 18:09:56 +00:00
parent b3a80d5a50
commit c921567831
9 changed files with 257 additions and 142 deletions

View File

@ -41,7 +41,7 @@ limitations under the License.
.mx_BaseAvatar_image {
object-fit: cover;
border-radius: 40px;
border-radius: 125px;
vertical-align: top;
background-color: $avatar-bg-color;
}

View File

@ -15,47 +15,46 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_CallView {
border-radius: 10px;
background-color: $input-lighter-bg-color;
padding-left: 8px;
padding-right: 8px;
// XXX: CallContainer sets pointer-events: none - should probably be set back in a better place
pointer-events: initial;
}
.mx_CallView_large {
padding-bottom: 10px;
.mx_CallView_voice {
height: 360px;
}
}
.mx_CallView_pip {
width: 320px;
.mx_CallView_voice {
height: 180px
}
}
.mx_CallView_voice {
display: flex;
align-items: center;
justify-content: center;
background-color: $inverted-bg-color;
}
/*
.mx_CallView_voice {
background-color: $accent-color;
color: $accent-fg-color;
cursor: pointer;
padding: 6px;
font-weight: bold;
border-radius: 8px;
min-width: 200px;
display: flex;
align-items: center;
img {
margin: 4px;
margin-right: 10px;
}
> div {
display: flex;
flex-direction: column;
// Hacky vertical align
padding-top: 3px;
}
> div > p,
> div > h1 {
padding: 0;
margin: 0;
font-size: $font-13px;
line-height: $font-15px;
}
> div > p {
font-weight: bold;
}
> * {
flex-grow: 0;
flex-shrink: 0;
}
text-align: center;
vertical-align: middle;
}
.mx_CallView_hangup {
@ -92,6 +91,7 @@ limitations under the License.
background-color: $primary-fg-color;
}
}
*/
.mx_CallView_video {
width: 100%;
@ -99,3 +99,76 @@ limitations under the License.
z-index: 30;
}
.mx_CallView_header {
height: 44px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: left;
.mx_BaseAvatar {
margin-right: 12px;
}
}
.mx_CallView_header_callType {
font-weight: bold;
vertical-align: middle;
}
.mx_CallView_header_controls {
margin-left: auto;
}
.mx_CallView_header_control_fullscreen {
display: inline-block;
vertical-align: middle;
cursor: pointer;
&::before {
content: '';
display: inline-block;
height: 20px;
width: 20px;
vertical-align: middle;
background-color: $secondary-fg-color;
mask-repeat: no-repeat;
mask-size: contain;
mask-position: center;
mask-image: url('$(res)/img/element-icons/call/fullscreen.svg');
}
}
.mx_CallView_header_roomName {
font-weight: bold;
font-size: 12px;
line-height: initial;
}
.mx_CallView_header_callTypeSmall {
font-size: 12px;
color: $secondary-fg-color;
line-height: initial;
}
.mx_CallView_header_phoneIcon {
display: inline-block;
margin-right: 6px;
height: 16px;
width: 16px;
vertical-align: middle;
&::before {
content: '';
display: inline-block;
vertical-align: top;
height: 16px;
width: 16px;
background-color: $warning-color;
mask-repeat: no-repeat;
mask-size: contain;
mask-position: center;
mask-image: url('$(res)/img/element-icons/call/voice-call.svg');
}
}

View File

@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_VideoFeed video {
/*.mx_VideoFeed video {
width: 100%;
}
}*/
.mx_VideoFeed_remote {
width: 100%;
@ -28,16 +28,17 @@ limitations under the License.
width: 25%;
height: 25%;
position: absolute;
left: 10px;
bottom: 10px;
right: 10px;
top: 10px;
z-index: 100;
border-radius: 4px;
}
.mx_VideoFeed_local video {
/*.mx_VideoFeed_local video {
width: auto;
height: 100%;
}
}*/
.mx_VideoFeed_mirror video {
.mx_VideoFeed_mirror {
transform: scale(-1, 1);
}

View File

@ -1,28 +0,0 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
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';
interface IProps {
}
const PulsedAvatar: React.FC<IProps> = (props) => {
return <div className="mx_PulsedAvatar">
{props.children}
</div>;
};
export default PulsedAvatar;

View File

@ -26,6 +26,15 @@ import PersistentApp from "../elements/PersistentApp";
import SettingsStore from "../../../settings/SettingsStore";
import { CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
const SHOW_CALL_IN_STATES = [
CallState.Connected,
CallState.InviteSent,
CallState.Connecting,
CallState.CreateAnswer,
CallState.CreateOffer,
CallState.WaitLocalMedia,
];
interface IProps {
}
@ -94,14 +103,13 @@ export default class CallPreview extends React.Component<IProps, IState> {
const callForRoom = CallHandler.sharedInstance().getCallForRoom(this.state.roomId);
const showCall = (
this.state.activeCall &&
this.state.activeCall.state === CallState.Connected &&
SHOW_CALL_IN_STATES.includes(this.state.activeCall.state) &&
!callForRoom
);
if (showCall) {
return (
<CallView
className="mx_CallPreview"
onClick={this.onCallViewClick}
showHangup={true}
/>

View File

@ -21,10 +21,8 @@ import dis from '../../../dispatcher/dispatcher';
import CallHandler from '../../../CallHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
import VideoFeed, { VideoFeedType } from "./VideoFeed";
import RoomAvatar from "../avatars/RoomAvatar";
import PulsedAvatar from '../avatars/PulsedAvatar';
import { CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
import { CallEvent } from 'matrix-js-sdk/src/webrtc/call';
@ -43,9 +41,6 @@ interface IProps {
// in a way that is likely to cause a resize.
onResize?: any;
// classname applied to view,
className?: string;
// Whether to show the hang up icon:W
showHangup?: boolean;
}
@ -85,7 +80,7 @@ function exitFullscreen() {
export default class CallView extends React.Component<IProps, IState> {
private dispatcherRef: string;
private container = createRef<HTMLDivElement>();
private contentRef = createRef<HTMLDivElement>();
constructor(props: IProps) {
super(props);
@ -111,11 +106,11 @@ export default class CallView extends React.Component<IProps, IState> {
private onAction = (payload) => {
switch (payload.action) {
case 'video_fullscreen': {
if (!this.container.current) {
if (!this.contentRef.current) {
return;
}
if (payload.fullscreen) {
requestFullscreen(this.container.current);
requestFullscreen(this.contentRef.current);
} else if (getFullScreenElement()) {
exitFullscreen();
}
@ -144,11 +139,6 @@ export default class CallView extends React.Component<IProps, IState> {
if (this.props.room) {
const roomId = this.props.room.roomId;
call = CallHandler.sharedInstance().getCallForRoom(roomId);
// We don't currently show voice calls in this view when in the room:
// they're represented in the room status bar at the bottom instead
// (but this will all change with the new designs)
if (call && call.type == CallType.Voice) call = null;
} else {
call = CallHandler.sharedInstance().getAnyActiveCall();
// Ignore calls if we can't get the room associated with them.
@ -160,7 +150,7 @@ export default class CallView extends React.Component<IProps, IState> {
}
}
if (call && call.state == CallState.Ended) return null;
if (call && [CallState.Ended, CallState.Ringing].includes(call.state)) return null;
return call;
}
@ -177,11 +167,49 @@ export default class CallView extends React.Component<IProps, IState> {
});
};
public render() {
let view: React.ReactNode;
private onFullscreenClick = () => {
dis.dispatch({
action: 'video_fullscreen',
fullscreen: true,
});
};
if (this.state.call) {
if (this.state.call.type === "voice") {
public render() {
if (!this.state.call) return null;
const client = MatrixClientPeg.get();
const callRoom = client.getRoom(this.state.call.roomId);
//const callControls = <div className="mx_CallView_callControls">
//</div>;
// The 'content' for the call, ie. the videos for a video call and profile picture
// for voice calls (fills the bg)
let contentView: React.ReactNode;
if (this.state.call.type === CallType.Video) {
// if we're fullscreen, we don't want to set a maxHeight on the video element.
const maxVideoHeight = getFullScreenElement() ? null : this.props.maxVideoHeight;
contentView = <div className="mx_CallView_video" ref={this.contentRef}>
<VideoFeed type={VideoFeedType.Remote} call={this.state.call} onResize={this.props.onResize}
maxHeight={maxVideoHeight}
/>
<VideoFeed type={VideoFeedType.Local} call={this.state.call} />
</div>;
} else {
const avatarSize = this.props.room ? 200 : 75;
contentView = <div className="mx_CallView_voice">
<RoomAvatar
room={callRoom}
height={avatarSize}
width={avatarSize}
/>
</div>;
}
/*
if (!this.props.room) {
const client = MatrixClientPeg.get();
const callRoom = client.getRoom(this.state.call.roomId);
@ -220,8 +248,10 @@ export default class CallView extends React.Component<IProps, IState> {
<VideoFeed type={VideoFeedType.Local} call={this.state.call} />
</div>;
}
}
*/
/*
let hangup: React.ReactNode;
if (this.props.showHangup) {
hangup = <div
@ -234,10 +264,45 @@ export default class CallView extends React.Component<IProps, IState> {
}}
/>;
}
*/
return <div className={this.props.className} ref={this.container}>
{view}
{hangup}
const callTypeText = this.state.call.type === CallType.Video ? _t("Video Call") : _t("Voice Call");
let myClassName;
let fullScreenButton;
if (this.state.call.type === CallType.Video) {
fullScreenButton = <div className="mx_CallView_header_control_fullscreen"
onClick={this.onFullscreenClick} title={_t("Fill screen")}
/>;
}
const headerControls = <div className="mx_CallView_header_controls">
{fullScreenButton}
</div>;
let header: React.ReactNode;
if (this.props.room) {
header = <div className="mx_CallView_header">
<div className="mx_CallView_header_phoneIcon"></div>
<span className="mx_CallView_header_callType">{callTypeText}</span>
{headerControls}
</div>;
myClassName = 'mx_CallView_large';
} else {
header = <div className="mx_CallView_header">
<RoomAvatar room={callRoom} height={32} width={32} />
<div>
<div className="mx_CallView_header_roomName">{callRoom.name}</div>
<div className="mx_CallView_header_callTypeSmall">{callTypeText}</div>
</div>
{headerControls}
</div>;
myClassName = 'mx_CallView_pip';
}
return <div className={"mx_CallView " + myClassName}>
{header}
{contentView}
</div>;
}
}

View File

@ -22,7 +22,6 @@ import dis from '../../../dispatcher/dispatcher';
import { _t } from '../../../languageHandler';
import { ActionPayload } from '../../../dispatcher/payloads';
import CallHandler from '../../../CallHandler';
import PulsedAvatar from '../avatars/PulsedAvatar';
import RoomAvatar from '../avatars/RoomAvatar';
import FormButton from '../elements/FormButton';
import { CallState } from 'matrix-js-sdk/lib/webrtc/call';
@ -108,13 +107,11 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
return <div className="mx_IncomingCallBox">
<div className="mx_IncomingCallBox_CallerInfo">
<PulsedAvatar>
<RoomAvatar
room={room}
height={32}
width={32}
/>
</PulsedAvatar>
<div>
<h1>{caller}</h1>
<p>{incomingCallText}</p>

View File

@ -73,8 +73,6 @@ export default class VideoFeed extends React.Component<IProps> {
let videoStyle = {};
if (this.props.maxHeight) videoStyle = { maxHeight: this.props.maxHeight };
return <div className={classnames(videoClasses)}>
<video ref={this.vid} style={videoStyle}></video>
</div>;
return <video className={classnames(videoClasses)} ref={this.vid} style={videoStyle} />;
}
}

View File

@ -529,8 +529,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!",
"Active call": "Active call",
"Call Paused": "Call Paused",
"Video Call": "Video Call",
"Voice Call": "Voice Call",
"Unknown caller": "Unknown caller",
"Incoming voice call": "Incoming voice call",
"Incoming video call": "Incoming video call",
@ -2123,6 +2123,7 @@
"%(count)s <resendText>Resend all</resendText> or <cancelText>cancel all</cancelText> now. You can also select individual messages to resend or cancel.|one": "<resendText>Resend message</resendText> or <cancelText>cancel message</cancelText> now.",
"Calling...": "Calling...",
"Call connecting...": "Call connecting...",
"Active call": "Active call",
"Starting camera...": "Starting camera...",
"Starting microphone...": "Starting microphone...",
"Connectivity to the server has been lost.": "Connectivity to the server has been lost.",