Fix webcam size after minimize the presentation #7570

This commit is contained in:
Vitor Mateus 2019-06-07 17:45:54 -03:00
parent 7b59f1d309
commit 0c81eda94e
6 changed files with 168 additions and 12 deletions

View File

@ -425,7 +425,20 @@ export default class WebcamDraggableOverlay extends Component {
hideOverlay, hideOverlay,
disableVideo, disableVideo,
audioModalIsOpen, audioModalIsOpen,
refMediaContainer,
} = this.props; } = this.props;
const { current: mediaContainer } = refMediaContainer;
let mediaContainerRect;
let mediaHeight;
if (mediaContainer) {
mediaContainerRect = mediaContainer.getBoundingClientRect();
const {
height,
} = mediaContainerRect;
mediaHeight = height;
}
const { const {
dragging, dragging,
@ -441,6 +454,14 @@ export default class WebcamDraggableOverlay extends Component {
isMinWidth, isMinWidth,
} = this.state; } = this.state;
console.log(
'%c swapLayout %s',
'background:black;color:#fff;',
swapLayout,
);
const webcamBySelectorCount = WebcamDraggableOverlay.getWebcamBySelectorCount(); const webcamBySelectorCount = WebcamDraggableOverlay.getWebcamBySelectorCount();
const contentClassName = cx({ const contentClassName = cx({
@ -523,6 +544,8 @@ export default class WebcamDraggableOverlay extends Component {
? ( ? (
<VideoProviderContainer <VideoProviderContainer
cursor={cursor()} cursor={cursor()}
swapLayout={swapLayout}
mediaHeight={mediaHeight}
onMount={this.videoMounted} onMount={this.videoMounted}
onUpdate={this.videoUpdated} onUpdate={this.videoUpdated}
/> />

View File

@ -190,9 +190,13 @@ class VideoProvider extends Component {
&& peer.peerConnection.getRemoteStreams().length > 0; && peer.peerConnection.getRemoteStreams().length > 0;
if (hasLocalStream) { if (hasLocalStream) {
this.customGetStats(peer.peerConnection, peer.peerConnection.getLocalStreams()[0].getVideoTracks()[0], (stats => updateWebcamStats(id, stats)), true); this.customGetStats(peer.peerConnection,
peer.peerConnection.getLocalStreams()[0].getVideoTracks()[0],
(stats => updateWebcamStats(id, stats)), true);
} else if (hasRemoteStream) { } else if (hasRemoteStream) {
this.customGetStats(peer.peerConnection, peer.peerConnection.getRemoteStreams()[0].getVideoTracks()[0], (stats => updateWebcamStats(id, stats)), true); this.customGetStats(peer.peerConnection,
peer.peerConnection.getRemoteStreams()[0].getVideoTracks()[0],
(stats => updateWebcamStats(id, stats)), true);
} }
}); });
}, 5000); }, 5000);
@ -833,9 +837,9 @@ class VideoProvider extends Component {
let videoBitrate; let videoBitrate;
if (videoStats.packetsReceived > 0) { // Remote video if (videoStats.packetsReceived > 0) { // Remote video
videoLostPercentage = ((videoStats videoLostPercentage = ((videoStats.packetsLost / (
.packetsLost / ((videoStats (videoStats.packetsLost + videoStats.packetsReceived) * 100
.packetsLost + videoStats.packetsReceived) * 100)) || 0).toFixed(1); )) || 0).toFixed(1);
videoBitrate = Math.floor(videoKbitsReceivedPerSecond || 0); videoBitrate = Math.floor(videoKbitsReceivedPerSecond || 0);
videoLostRecentPercentage = ((videoIntervalPacketsLost / ((videoIntervalPacketsLost videoLostRecentPercentage = ((videoIntervalPacketsLost / ((videoIntervalPacketsLost
+ videoIntervalPacketsReceived) * 100)) || 0).toFixed(1); + videoIntervalPacketsReceived) * 100)) || 0).toFixed(1);
@ -1005,10 +1009,18 @@ class VideoProvider extends Component {
const { socketOpen } = this.state; const { socketOpen } = this.state;
if (!socketOpen) return null; if (!socketOpen) return null;
const { users, enableVideoStats, cursor } = this.props; const {
users,
enableVideoStats,
cursor,
swapLayout,
mediaHeight,
} = this.props;
return ( return (
<VideoList <VideoList
cursor={cursor} cursor={cursor}
swapLayout={swapLayout}
mediaHeight={mediaHeight}
users={users} users={users}
onMount={this.createVideoTag} onMount={this.createVideoTag}
getStats={this.getStats} getStats={this.getStats}

View File

@ -11,6 +11,8 @@ const VideoProviderContainer = ({ children, ...props }) => {
export default withTracker(props => ({ export default withTracker(props => ({
cursor: props.cursor, cursor: props.cursor,
swapLayout: props.swapLayout,
mediaHeight: props.mediaHeight,
meetingId: VideoService.meetingId(), meetingId: VideoService.meetingId(),
users: VideoService.getAllUsersVideo(), users: VideoService.getAllUsersVideo(),
userId: VideoService.userId(), userId: VideoService.userId(),

View File

@ -52,7 +52,15 @@ class VideoList extends Component {
renderVideoList() { renderVideoList() {
const { const {
intl, users, onMount, getStats, stopGettingStats, enableVideoStats, cursor, intl,
users,
onMount,
getStats,
stopGettingStats,
enableVideoStats,
cursor,
swapLayout,
mediaHeight,
} = this.props; } = this.props;
const { focusedId } = this.state; const { focusedId } = this.state;
@ -73,7 +81,8 @@ class VideoList extends Component {
<div <div
key={user.id} key={user.id}
className={cx({ className={cx({
[styles.videoListItem]: true, [styles.videoListItem]: !swapLayout,
[styles.videoListItemSwapLayout]: swapLayout,
[styles.focused]: focusedId === user.id && users.length > 2, [styles.focused]: focusedId === user.id && users.length > 2,
})} })}
style={{ style={{
@ -88,6 +97,8 @@ class VideoList extends Component {
getStats={(videoRef, callback) => getStats(user.id, videoRef, callback)} getStats={(videoRef, callback) => getStats(user.id, videoRef, callback)}
stopGettingStats={() => stopGettingStats(user.id)} stopGettingStats={() => stopGettingStats(user.id)}
enableVideoStats={enableVideoStats} enableVideoStats={enableVideoStats}
swapLayout={swapLayout}
mediaHeight={mediaHeight}
/> />
</div> </div>
); );
@ -100,6 +111,8 @@ class VideoList extends Component {
<div <div
ref={(ref) => { this.canvas = ref; }} ref={(ref) => { this.canvas = ref; }}
className={styles.videoCanvas} className={styles.videoCanvas}
// TODO adicionar videoCanvasSwapLayout quando for swaplayout
> >
{!users.length ? null : ( {!users.length ? null : (
<div <div

View File

@ -11,13 +11,29 @@
--audio-indicator-fs: 75%; --audio-indicator-fs: 75%;
position: relative; position: relative;
width: 100%; width: 100%;
min-height: calc(var(--video-width) / var(--video-ratio));
height: 100%;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
}
.videoCanvasSwapLayout {
--cam-dropdown-width: 70%;
--audio-indicator-width: 1.12rem;
--audio-indicator-fs: 75%;
position: relative;
width: 100%;
min-height: calc(var(--video-width) / var(--video-ratio)); min-height: calc(var(--video-width) / var(--video-ratio));
top: 0;
left: 0;
right: 0;
bottom: 0;
align-items: center;
justify-content: center;
} }
.videoList { .videoList {
@ -41,6 +57,24 @@
} }
} }
.videoListSwapLayout {
display: grid;
padding: 10px;
border-radius: 5px;
min-height: calc(var(--video-width) / var(--video-ratio));
grid-template-columns: repeat(auto-fit, minmax(var(--video-width), 1fr));
grid-auto-columns: minmax(var(--video-width), 1fr);
grid-auto-rows: 1fr;
grid-gap: 5px;
align-items: center;
justify-content: center;
grid-auto-flow: column dense;
@include mq($medium-up) {
grid-gap: 10px;
}
}
.videoListItem { .videoListItem {
display: flex; display: flex;
max-width: fit-content; max-width: fit-content;
@ -62,6 +96,25 @@
min-height: calc(var(--video-width) / var(--video-ratio)); min-height: calc(var(--video-width) / var(--video-ratio));
} }
.videoListItemSwapLayout {
display: flex;
max-width: -moz-fit-content;
max-height: -moz-fit-content;
width: 100%;
height: 100%;
&.focused {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
width: 100%;
min-width: 100%;
max-width: 100%;
height: 100%;
min-height: 100%;
max-height: 100%;
}
}
.content { .content {
position: relative; position: relative;
min-width: 100%; min-width: 100%;
@ -107,6 +160,48 @@
} }
} }
.contentSwapLayout {
position: relative;
min-width: 100%;
height: 100%;
min-height: 100%;
border-radius: 5px;
background-color: var(--color-gray);
width: 100%;
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 5px solid var(--color-white-with-transparency);
border-radius: 5px;
opacity: 0;
pointer-events: none;
:global(.animationsEnabled) & {
transition: opacity .1s;
}
}
&.talking::after {
opacity: 1;
}
.focused & {
width: 100%;
min-width: 100%;
max-width: 100%;
height: 100%;
min-height: 100%;
max-height: 100%;
}
}
.contentLoading { .contentLoading {
width: var(--video-width); width: var(--video-width);
min-width: var(--video-width); min-width: var(--video-width);
@ -114,8 +209,12 @@
min-height: calc(var(--video-width) / var(--video-ratio)); min-height: calc(var(--video-width) / var(--video-ratio));
} }
%media-area { .contentLoadingSwapLayout {
width: 100%;
height: 100%;
}
%media-area {
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;

View File

@ -129,7 +129,9 @@ class VideoListItem extends Component {
render() { render() {
const { showStats, stats, videoIsReady } = this.state; const { showStats, stats, videoIsReady } = this.state;
const { user, numOfUsers } = this.props; const {
user, numOfUsers, swapLayout, mediaHeight,
} = this.props;
const availableActions = this.getAvailableActions(); const availableActions = this.getAvailableActions();
const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false; const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false;
@ -138,13 +140,18 @@ class VideoListItem extends Component {
return ( return (
<div className={cx({ <div className={cx({
[styles.content]: true, [styles.content]: !swapLayout,
[styles.contentSwapLayout]: swapLayout,
[styles.talking]: user.isTalking, [styles.talking]: user.isTalking,
[styles.contentLoading]: !videoIsReady, [styles.contentLoading]: !videoIsReady && !swapLayout,
[styles.contentLoadingSwapLayout]: !videoIsReady && swapLayout,
})} })}
> >
{!videoIsReady && <div className={styles.connecting} />} {!videoIsReady && <div className={styles.connecting} />}
<video <video
style={{
maxHeight: mediaHeight,
}}
muted muted
className={cx({ className={cx({
[styles.media]: true, [styles.media]: true,