bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/layout/layout-manager.jsx
Vitor Mateus ecc8f4a056 wip
2020-07-20 16:16:39 -03:00

530 lines
16 KiB
JavaScript

import React, { Component, Fragment } from 'react';
import Storage from '/imports/ui/services/storage/session';
import { Session } from 'meteor/session';
const windowWidth = () => window.innerWidth;
const windowHeight = () => window.innerHeight;
const min = (value1, value2) => (value1 <= value2 ? value1 : value2);
const max = (value1, value2) => (value1 >= value2 ? value1 : value2);
// values based on sass file
const USERLIST_MIN_WIDTH = 150;
const USERLIST_MAX_WIDTH = 240;
const CHAT_MIN_WIDTH = 150;
const CHAT_MAX_WIDTH = 335;
const NAVBAR_HEIGHT = 85;
const ACTIONSBAR_HEIGHT = 42;
const WEBCAMSAREA_MIN_PERCENT = 0.2;
const WEBCAMSAREA_MAX_PERCENT = 0.8;
const PRESENTATIONAREA_MIN_PERCENT = 0.2;
const PRESENTATIONAREA_MIN_WIDTH = 385; // Value based on presentation toolbar
const PRESENTATIONAREA_MAX_PERCENT = 0.8;
const storageLayoutData = () => Storage.getItem('layoutData');
class LayoutManager extends Component {
constructor(props) {
super(props);
this.setLayoutSizes = this.setLayoutSizes.bind(this);
this.calculatesLayout = this.calculatesLayout.bind(this);
}
componentDidMount() {
this.setLayoutSizes();
window.addEventListener('resize', _.throttle(() => this.setLayoutSizes(), 200));
window.addEventListener('userListResizeChanged', () => {
const userlistChanged = true;
const chatChanged = false;
this.setLayoutSizes(userlistChanged, chatChanged);
});
window.addEventListener('chatResizeChanged', () => {
const userlistChanged = false;
const chatChanged = true;
this.setLayoutSizes(userlistChanged, chatChanged);
});
window.addEventListener('autoArrangeChanged', () => {
setTimeout(() => this.setLayoutSizes(), 200);
});
}
componentDidUpdate(prevProps) {
const { usersVideo, layoutContextState } = this.props;
const { usersVideo: prevUsersVideo, layoutContextState: prevLayoutContextState } = prevProps;
const {
webcamsPlacement,
webcamsAreaSize,
presentationSlideSize,
} = layoutContextState;
const {
webcamsPlacement: prevWebcamsPlacement,
webcamsAreaSize: prevWebcamsAreaSize,
presentationSlideSize: prevPresentationSlideSize,
} = prevLayoutContextState;
if (usersVideo.length !== prevUsersVideo.length) {
setTimeout(() => this.setLayoutSizes(), 500);
}
if (webcamsPlacement !== prevWebcamsPlacement
|| presentationSlideSize !== prevPresentationSlideSize) {
this.setLayoutSizes();
}
if (webcamsAreaSize.width !== prevWebcamsAreaSize.width
|| webcamsAreaSize.height !== prevWebcamsAreaSize.height) {
this.setLayoutSizes(true, true, webcamsAreaSize);
}
}
setLayoutSizes(userlistChanged = false, chatChanged = false, webcamsAreaSize = null) {
const { layoutContextDispatch } = this.props;
const layoutSizes = this
.calculatesLayout(userlistChanged, chatChanged, webcamsAreaSize);
layoutContextDispatch(
{
type: 'setWindowSize',
value: {
width: windowWidth(),
height: windowHeight(),
},
},
);
layoutContextDispatch(
{
type: 'setMediaBounds',
value: {
width: layoutSizes.mediaBounds.width,
height: layoutSizes.mediaBounds.height,
top: layoutSizes.mediaBounds.top,
left: layoutSizes.mediaBounds.left,
},
},
);
layoutContextDispatch(
{
type: 'setUserListSize',
value: {
width: layoutSizes.userListSize.width,
},
},
);
layoutContextDispatch(
{
type: 'setChatSize',
value: {
width: layoutSizes.chatSize.width,
},
},
);
layoutContextDispatch(
{
type: 'setWebcamsAreaSize',
value: {
width: layoutSizes.webcamsAreaSize.width,
height: layoutSizes.webcamsAreaSize.height,
},
},
);
layoutContextDispatch(
{
type: 'setPresentationAreaSize',
value: {
width: layoutSizes.presentationAreaSize.width,
height: layoutSizes.presentationAreaSize.height,
},
},
);
const newLayoutData = {
windowSize: {
width: windowWidth(),
height: windowHeight(),
},
mediaBounds: {
width: layoutSizes.mediaBounds.width,
height: layoutSizes.mediaBounds.height,
top: layoutSizes.mediaBounds.top,
left: layoutSizes.mediaBounds.left,
},
userListSize: {
width: layoutSizes.userListSize.width,
},
chatSize: {
width: layoutSizes.chatSize.width,
},
webcamsAreaSize: {
width: layoutSizes.webcamsAreaSize.width,
height: layoutSizes.webcamsAreaSize.height,
},
presentationAreaSize: {
width: layoutSizes.presentationAreaSize.width,
height: layoutSizes.presentationAreaSize.height,
},
};
Storage.setItem('layoutData', newLayoutData);
window.dispatchEvent(new Event('layoutSizesSets'));
}
calculatesPanelsSize(userlistChanged, chatChanged) {
const { layoutContextState } = this.props;
const {
userListSize: userListSizeContext,
chatSize: chatSizeContext,
} = layoutContextState;
const openPanel = Session.get('openPanel');
const storageLData = storageLayoutData();
let storageUserListWidth;
let storageChatWidth;
if (storageLData) {
storageUserListWidth = storageLData.userListSize.width;
storageChatWidth = storageLData.chatSize.width;
}
let newUserListSize;
let newChatSize;
if (userlistChanged || chatChanged) {
newUserListSize = userListSizeContext;
newChatSize = chatSizeContext;
} else {
if (!storageUserListWidth) {
newUserListSize = {
width: min(max((windowWidth() * 0.1), USERLIST_MIN_WIDTH), USERLIST_MAX_WIDTH),
};
} else {
newUserListSize = {
width: storageUserListWidth,
};
}
if (!storageChatWidth) {
newChatSize = {
width: min(max((windowWidth() * 0.2), CHAT_MIN_WIDTH), CHAT_MAX_WIDTH),
};
} else {
newChatSize = {
width: storageChatWidth,
};
}
}
if (openPanel === 'userlist') {
newChatSize = {
width: 0,
};
}
if (!openPanel) {
newUserListSize = {
width: 0,
};
newChatSize = {
width: 0,
};
}
return {
newUserListSize,
newChatSize,
};
}
calculatesWebcamsAreaSize(
mediaAreaWidth, mediaAreaHeight, presentationWidth = null, presentationHeight = null,
) {
const {
layoutContextState,
layoutContextDispatch,
usersVideo,
} = this.props;
const { webcamsPlacement } = layoutContextState;
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
const webcamsAreaUserSetsHeight = Storage.getItem('webcamsAreaUserSetsHeight');
const webcamsAreaUserSetsWidth = Storage.getItem('webcamsAreaUserSetsWidth');
let newWebcamAreaHeight;
let newWebcamAreaWidth;
if (usersVideo.length < 1) {
return {
newWebcamAreaWidth: 0,
newWebcamAreaHeight: 0,
};
}
if (presentationWidth === null || presentationHeight === null) {
if (webcamsPlacement === 'left' || webcamsPlacement === 'right') {
newWebcamAreaWidth = min(
max(
webcamsAreaUserSetsWidth && !autoArrangeLayout
? webcamsAreaUserSetsWidth : mediaAreaWidth * WEBCAMSAREA_MIN_PERCENT,
mediaAreaWidth * WEBCAMSAREA_MIN_PERCENT,
),
mediaAreaWidth * WEBCAMSAREA_MAX_PERCENT,
);
if ((mediaAreaWidth - newWebcamAreaWidth) < PRESENTATIONAREA_MIN_WIDTH) {
newWebcamAreaWidth = mediaAreaWidth - PRESENTATIONAREA_MIN_WIDTH;
}
newWebcamAreaHeight = mediaAreaHeight;
} else {
newWebcamAreaWidth = mediaAreaWidth;
newWebcamAreaHeight = min(
max(
webcamsAreaUserSetsHeight && !autoArrangeLayout
? webcamsAreaUserSetsHeight : mediaAreaHeight * WEBCAMSAREA_MIN_PERCENT,
mediaAreaHeight * WEBCAMSAREA_MIN_PERCENT,
),
mediaAreaHeight * WEBCAMSAREA_MAX_PERCENT,
);
}
}
if (autoArrangeLayout) {
if ((mediaAreaWidth - presentationWidth) > (mediaAreaHeight - presentationHeight)) {
layoutContextDispatch(
{
type: 'setWebcamsPlacement',
value: 'left',
},
);
newWebcamAreaWidth = min(
max(
mediaAreaWidth - presentationWidth,
mediaAreaWidth * WEBCAMSAREA_MIN_PERCENT,
),
mediaAreaWidth * WEBCAMSAREA_MAX_PERCENT,
);
newWebcamAreaHeight = mediaAreaHeight;
} else {
layoutContextDispatch(
{
type: 'setWebcamsPlacement',
value: 'top',
},
);
newWebcamAreaWidth = mediaAreaWidth;
newWebcamAreaHeight = min(
max(
mediaAreaHeight - presentationHeight,
mediaAreaHeight * WEBCAMSAREA_MIN_PERCENT,
),
mediaAreaHeight * WEBCAMSAREA_MAX_PERCENT,
);
}
}
return {
newWebcamAreaWidth,
newWebcamAreaHeight,
};
}
calculatesPresentationMaxSize(
mediaAreaWidth, mediaAreaHeight, presentationSlideWidth, presentationSlideHeight,
) {
const { usersVideo, layoutContextState } = this.props;
const { webcamsPlacement } = layoutContextState;
let presentationWidthAvailable;
let presentationHeightAvailable;
if (usersVideo.length > 0) {
if (webcamsPlacement === 'top' || webcamsPlacement === 'bottom') {
presentationWidthAvailable = mediaAreaWidth;
presentationHeightAvailable = mediaAreaHeight * PRESENTATIONAREA_MAX_PERCENT;
} else {
presentationWidthAvailable = mediaAreaWidth * PRESENTATIONAREA_MAX_PERCENT;
presentationHeightAvailable = mediaAreaHeight;
}
} else {
presentationWidthAvailable = mediaAreaWidth;
presentationHeightAvailable = mediaAreaHeight;
}
let presentationWidth;
let presentationHeight;
if (presentationSlideWidth > presentationSlideHeight
|| presentationSlideWidth === presentationSlideHeight) {
presentationWidth = presentationWidthAvailable;
presentationHeight = (presentationWidthAvailable * presentationSlideHeight)
/ presentationSlideWidth;
// if overflow
if (presentationHeight > presentationHeightAvailable) {
presentationWidth = (presentationHeightAvailable * presentationWidth) / presentationHeight;
presentationHeight = presentationHeightAvailable;
}
}
if (presentationSlideHeight > presentationSlideWidth) {
presentationWidth = (presentationHeightAvailable * presentationSlideWidth)
/ presentationSlideHeight;
presentationHeight = presentationHeightAvailable;
// if overflow
if (presentationWidth > presentationWidthAvailable) {
presentationHeight = (presentationWidthAvailable * presentationWidth) / presentationHeight;
presentationWidth = presentationWidthAvailable;
}
}
return {
presentationWidth,
presentationHeight,
};
}
calculatesPresentationAreaSize(
mediaAreaWidth, mediaAreaHeight, webcamAreaWidth = null, webcamAreaHeight = null,
) {
const {
layoutContextState,
usersVideo,
} = this.props;
const { webcamsPlacement, presentationSlideSize, autoArrangeLayout } = layoutContextState;
let newPresentationAreaWidth;
let newPresentationAreaHeight;
if (usersVideo.length < 1) {
return {
newPresentationAreaWidth: mediaAreaWidth,
newPresentationAreaHeight: mediaAreaHeight, // 20 is margins
};
}
const {
width: presentationSlideWidth,
height: presentationSlideHeight,
} = presentationSlideSize;
const presentationMaxSize = this.calculatesPresentationMaxSize(
mediaAreaWidth, mediaAreaHeight, presentationSlideWidth, presentationSlideHeight,
);
const { presentationWidth, presentationHeight } = presentationMaxSize;
// Se não vier valor da webcam, preciso ver se há vídeo
// Se tiver um video preciso verificar a área mínima da webcam
if (webcamAreaWidth === null || webcamAreaHeight === null) {
newPresentationAreaWidth = presentationWidth; // 30 is margins
newPresentationAreaHeight = presentationHeight; // 20 is margins
} else if (webcamsPlacement === 'left' || webcamsPlacement === 'right') {
newPresentationAreaWidth = mediaAreaWidth - webcamAreaWidth; // 30 is margins
newPresentationAreaHeight = mediaAreaHeight; // 20 is margins
} else {
newPresentationAreaWidth = mediaAreaWidth;
newPresentationAreaHeight = mediaAreaHeight - webcamAreaHeight; // 30 is margins
}
console.log('=== newPresentationAreaHeight', newPresentationAreaHeight);
console.log('=== mediaAreaHeight', mediaAreaHeight);
console.log('=== webcamAreaHeight', webcamAreaHeight);
console.log('=== mediaAreaHeight - webcamAreaHeight', mediaAreaHeight - webcamAreaHeight);
// if (newPresentationAreaWidth < (mediaAreaWidth * PRESENTATIONAREA_MIN_PERCENT)) {
// if (newPresentationAreaWidth < 400) {
// newPresentationAreaWidth = 400;
// } else {
// newPresentationAreaWidth = mediaAreaWidth * PRESENTATIONAREA_MIN_PERCENT;
// }
// }
return {
newPresentationAreaWidth: autoArrangeLayout
? newPresentationAreaWidth - 10 : newPresentationAreaWidth - 26,
newPresentationAreaHeight: newPresentationAreaHeight
< (mediaAreaHeight * PRESENTATIONAREA_MIN_PERCENT)
? mediaAreaHeight * PRESENTATIONAREA_MIN_PERCENT
: newPresentationAreaHeight - 100,
};
}
calculatesLayout(userlistChanged = false, chatChanged = false) {
const {
layoutContextState,
} = this.props;
const { presentationIsFullscreen } = layoutContextState;
const autoArrangeLayout = Storage.getItem('autoArrangeLayout');
const panelsSize = this.calculatesPanelsSize(userlistChanged, chatChanged);
const { newUserListSize, newChatSize } = panelsSize;
const mediaAreaHeight = windowHeight() - (NAVBAR_HEIGHT + ACTIONSBAR_HEIGHT);
const mediaAreaWidth = windowWidth() - (newUserListSize.width + newChatSize.width);
const newMediaBounds = {
width: mediaAreaWidth,
height: mediaAreaHeight,
top: NAVBAR_HEIGHT,
left: newUserListSize.width + newChatSize.width,
};
let webcamsSize;
let presentationSize;
if (autoArrangeLayout) {
presentationSize = this.calculatesPresentationAreaSize(mediaAreaWidth, mediaAreaHeight);
webcamsSize = this.calculatesWebcamsAreaSize(
mediaAreaWidth,
mediaAreaHeight,
presentationSize.newPresentationAreaWidth,
presentationSize.newPresentationAreaHeight,
);
} else {
webcamsSize = this.calculatesWebcamsAreaSize(mediaAreaWidth, mediaAreaHeight);
presentationSize = this.calculatesPresentationAreaSize(
mediaAreaWidth,
mediaAreaHeight,
webcamsSize.newWebcamAreaWidth,
webcamsSize.newWebcamAreaHeight,
);
}
const newWebcamsAreaSize = {
width: webcamsSize.newWebcamAreaWidth,
height: webcamsSize.newWebcamAreaHeight,
};
let newPresentationAreaSize;
if (!presentationIsFullscreen) {
newPresentationAreaSize = {
width: presentationSize.newPresentationAreaWidth,
height: presentationSize.newPresentationAreaHeight,
};
} else {
newPresentationAreaSize = {
width: windowWidth(),
height: windowHeight(),
};
}
return {
mediaBounds: newMediaBounds,
userListSize: newUserListSize,
chatSize: newChatSize,
webcamsAreaSize: newWebcamsAreaSize,
presentationAreaSize: newPresentationAreaSize,
};
}
render() {
return <Fragment />;
}
}
export default LayoutManager;
export {
USERLIST_MIN_WIDTH,
USERLIST_MAX_WIDTH,
CHAT_MIN_WIDTH,
CHAT_MAX_WIDTH,
NAVBAR_HEIGHT,
ACTIONSBAR_HEIGHT,
WEBCAMSAREA_MIN_PERCENT,
WEBCAMSAREA_MAX_PERCENT,
PRESENTATIONAREA_MIN_WIDTH,
};