commit
6e6a26f86a
|
@ -250,6 +250,7 @@
|
||||||
@import "./views/voice_messages/_Waveform.scss";
|
@import "./views/voice_messages/_Waveform.scss";
|
||||||
@import "./views/voip/_CallContainer.scss";
|
@import "./views/voip/_CallContainer.scss";
|
||||||
@import "./views/voip/_CallView.scss";
|
@import "./views/voip/_CallView.scss";
|
||||||
|
@import "./views/voip/_CallViewForRoom.scss";
|
||||||
@import "./views/voip/_DialPad.scss";
|
@import "./views/voip/_DialPad.scss";
|
||||||
@import "./views/voip/_DialPadContextMenu.scss";
|
@import "./views/voip/_DialPadContextMenu.scss";
|
||||||
@import "./views/voip/_DialPadModal.scss";
|
@import "./views/voip/_DialPadModal.scss";
|
||||||
|
|
|
@ -27,9 +27,12 @@ limitations under the License.
|
||||||
.mx_CallView_large {
|
.mx_CallView_large {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
margin: 5px 5px 5px 18px;
|
margin: 5px 5px 5px 18px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
.mx_CallView_voice {
|
.mx_CallView_voice {
|
||||||
height: 360px;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +107,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_CallView_video {
|
.mx_CallView_video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -177,6 +181,7 @@ limitations under the License.
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_CallView_header_callType {
|
.mx_CallView_header_callType {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||||
|
|
||||||
|
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_CallViewForRoom {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.mx_CallViewForRoom_ResizeWrapper {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&:hover .mx_CallViewForRoom_ResizeHandle {
|
||||||
|
// Need to use important to override element style attributes
|
||||||
|
// set by re-resizable
|
||||||
|
width: 100% !important;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
margin-top: 3px;
|
||||||
|
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
height: 4px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 64px;
|
||||||
|
|
||||||
|
background-color: $primary-fg-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_VideoFeed_remote {
|
.mx_VideoFeed_remote {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 100%;
|
height: 100%;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,8 +149,8 @@ export default class AuxPanel extends React.Component<IProps, IState> {
|
||||||
const callView = (
|
const callView = (
|
||||||
<CallViewForRoom
|
<CallViewForRoom
|
||||||
roomId={this.props.room.roomId}
|
roomId={this.props.room.roomId}
|
||||||
onResize={this.props.onResize}
|
|
||||||
maxVideoHeight={this.props.maxHeight}
|
maxVideoHeight={this.props.maxHeight}
|
||||||
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,6 @@ interface IProps {
|
||||||
// Another ongoing call to display information about
|
// Another ongoing call to display information about
|
||||||
secondaryCall?: MatrixCall,
|
secondaryCall?: MatrixCall,
|
||||||
|
|
||||||
// maxHeight style attribute for the video panel
|
|
||||||
maxVideoHeight?: number;
|
|
||||||
|
|
||||||
// a callback which is called when the content in the callview changes
|
// a callback which is called when the content in the callview changes
|
||||||
// in a way that is likely to cause a resize.
|
// in a way that is likely to cause a resize.
|
||||||
onResize?: any;
|
onResize?: any;
|
||||||
|
@ -96,9 +93,6 @@ function exitFullscreen() {
|
||||||
const CONTROLS_HIDE_DELAY = 1000;
|
const CONTROLS_HIDE_DELAY = 1000;
|
||||||
// Height of the header duplicated from CSS because we need to subtract it from our max
|
// 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
|
// height to get the max height of the video
|
||||||
const HEADER_HEIGHT = 44;
|
|
||||||
const BOTTOM_PADDING = 10;
|
|
||||||
const BOTTOM_MARGIN_TOP_BOTTOM = 10; // top margin plus bottom margin
|
|
||||||
const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the button (px)
|
const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the button (px)
|
||||||
|
|
||||||
@replaceableComponent("views.voip.CallView")
|
@replaceableComponent("views.voip.CallView")
|
||||||
|
@ -548,20 +542,9 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
localVideoFeed = <VideoFeed type={VideoFeedType.Local} call={this.props.call} />;
|
localVideoFeed = <VideoFeed type={VideoFeedType.Local} call={this.props.call} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're fullscreen, we don't want to set a maxHeight on the video element.
|
contentView = <div className={containerClasses} ref={this.contentRef} onMouseMove={this.onMouseMove}>
|
||||||
const maxVideoHeight = getFullScreenElement() || !this.props.maxVideoHeight ? null : (
|
|
||||||
this.props.maxVideoHeight - (HEADER_HEIGHT + BOTTOM_PADDING + BOTTOM_MARGIN_TOP_BOTTOM)
|
|
||||||
);
|
|
||||||
contentView = <div className={containerClasses}
|
|
||||||
ref={this.contentRef} onMouseMove={this.onMouseMove}
|
|
||||||
// Put the max height on here too because this div is ended up 4px larger than the content
|
|
||||||
// and is causing it to scroll, and I am genuinely baffled as to why.
|
|
||||||
style={{maxHeight: maxVideoHeight}}
|
|
||||||
>
|
|
||||||
{onHoldBackground}
|
{onHoldBackground}
|
||||||
<VideoFeed type={VideoFeedType.Remote} call={this.props.call} onResize={this.props.onResize}
|
<VideoFeed type={VideoFeedType.Remote} call={this.props.call} onResize={this.props.onResize} />
|
||||||
maxHeight={maxVideoHeight}
|
|
||||||
/>
|
|
||||||
{localVideoFeed}
|
{localVideoFeed}
|
||||||
{holdTransferContent}
|
{holdTransferContent}
|
||||||
{callControls}
|
{callControls}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import React from 'react';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
import CallView from './CallView';
|
import CallView from './CallView';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
|
import {Resizable} from "re-resizable";
|
||||||
|
import ResizeNotifier from "../../../utils/ResizeNotifier";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
@ -28,9 +30,7 @@ interface IProps {
|
||||||
// maxHeight style attribute for the video panel
|
// maxHeight style attribute for the video panel
|
||||||
maxVideoHeight?: number;
|
maxVideoHeight?: number;
|
||||||
|
|
||||||
// a callback which is called when the content in the callview changes
|
resizeNotifier: ResizeNotifier,
|
||||||
// in a way that is likely to cause a resize.
|
|
||||||
onResize?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -79,11 +79,50 @@ export default class CallViewForRoom extends React.Component<IProps, IState> {
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onResizeStart = () => {
|
||||||
|
this.props.resizeNotifier.startResizing();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResize = () => {
|
||||||
|
this.props.resizeNotifier.notifyTimelineHeightChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
private onResizeStop = () => {
|
||||||
|
this.props.resizeNotifier.stopResizing();
|
||||||
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
if (!this.state.call) return null;
|
if (!this.state.call) return null;
|
||||||
|
// We subtract 8 as it the margin-bottom of the mx_CallViewForRoom_ResizeWrapper
|
||||||
|
const maxHeight = this.props.maxVideoHeight - 8;
|
||||||
|
|
||||||
return <CallView call={this.state.call} pipMode={false}
|
return (
|
||||||
onResize={this.props.onResize} maxVideoHeight={this.props.maxVideoHeight}
|
<div className="mx_CallViewForRoom">
|
||||||
/>;
|
<Resizable
|
||||||
|
minHeight={380}
|
||||||
|
maxHeight={maxHeight}
|
||||||
|
enable={{
|
||||||
|
top: false,
|
||||||
|
right: false,
|
||||||
|
bottom: true,
|
||||||
|
left: false,
|
||||||
|
topRight: false,
|
||||||
|
bottomRight: false,
|
||||||
|
bottomLeft: false,
|
||||||
|
topLeft: false,
|
||||||
|
}}
|
||||||
|
onResizeStart={this.onResizeStart}
|
||||||
|
onResize={this.onResize}
|
||||||
|
onResizeStop={this.onResizeStop}
|
||||||
|
className="mx_CallViewForRoom_ResizeWrapper"
|
||||||
|
handleClasses={{bottom: "mx_CallViewForRoom_ResizeHandle"}}
|
||||||
|
>
|
||||||
|
<CallView
|
||||||
|
call={this.state.call}
|
||||||
|
pipMode={false}
|
||||||
|
/>
|
||||||
|
</Resizable>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,6 @@ interface IProps {
|
||||||
|
|
||||||
type: VideoFeedType,
|
type: VideoFeedType,
|
||||||
|
|
||||||
// maxHeight style attribute for the video element
|
|
||||||
maxHeight?: number,
|
|
||||||
|
|
||||||
// a callback which is called when the video element is resized
|
// a callback which is called when the video element is resized
|
||||||
// due to a change in video metadata
|
// due to a change in video metadata
|
||||||
onResize?: (e: Event) => void,
|
onResize?: (e: Event) => void,
|
||||||
|
@ -82,9 +79,6 @@ export default class VideoFeed extends React.Component<IProps> {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let videoStyle = {};
|
return <video className={classnames(videoClasses)} ref={this.vid} />;
|
||||||
if (this.props.maxHeight) videoStyle = { maxHeight: this.props.maxHeight };
|
|
||||||
|
|
||||||
return <video className={classnames(videoClasses)} ref={this.vid} style={videoStyle} />;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue