bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/layout/push-layout/pushLayoutEngine.jsx

293 lines
9.1 KiB
React
Raw Normal View History

2022-09-03 02:18:17 +08:00
import React from 'react';
import PropTypes from 'prop-types';
import { Meteor } from 'meteor/meteor';
import getFromUserSettings from '/imports/ui/services/users-settings';
import Settings from '/imports/ui/services/settings';
import MediaService from '/imports/ui/components/media/service';
import { LAYOUT_TYPE, ACTIONS } from '../enums';
import { isMobile } from '../utils';
import { updateSettings } from '/imports/ui/components/settings/service';
import { Session } from 'meteor/session';
2022-09-03 02:18:17 +08:00
const HIDE_PRESENTATION = window.meetingClientSettings.public.layout.hidePresentationOnJoin;
2022-09-03 02:18:17 +08:00
const equalDouble = (n1, n2) => {
const precision = 0.01;
return Math.abs(n1 - n2) <= precision;
};
const propTypes = {
cameraWidth: PropTypes.number,
cameraHeight: PropTypes.number,
cameraIsResizing: PropTypes.bool,
cameraPosition: PropTypes.string,
focusedCamera: PropTypes.string,
2022-09-15 23:01:31 +08:00
horizontalPosition: PropTypes.bool,
isMeetingLayoutResizing: PropTypes.bool,
2022-09-03 02:18:17 +08:00
isPresenter: PropTypes.bool,
isModerator: PropTypes.bool,
layoutContextDispatch: PropTypes.func,
meetingLayout: PropTypes.string,
meetingLayoutCameraPosition: PropTypes.string,
meetingLayoutFocusedCamera: PropTypes.string,
meetingLayoutVideoRate: PropTypes.number,
meetingPresentationIsOpen: PropTypes.bool,
meetingLayoutUpdatedAt: PropTypes.number,
presentationIsOpen: PropTypes.bool,
presentationVideoRate: PropTypes.number,
pushLayout: PropTypes.bool,
pushLayoutMeeting: PropTypes.bool,
selectedLayout: PropTypes.string,
setMeetingLayout: PropTypes.func,
setPushLayout: PropTypes.func,
2022-09-03 02:18:17 +08:00
shouldShowScreenshare: PropTypes.bool,
shouldShowExternalVideo: PropTypes.bool,
enforceLayout: PropTypes.string,
2024-01-30 21:03:11 +08:00
setLocalSettings: PropTypes.func.isRequired,
2022-09-03 02:18:17 +08:00
};
class PushLayoutEngine extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
const {
cameraWidth,
cameraHeight,
horizontalPosition,
layoutContextDispatch,
meetingLayout,
meetingLayoutCameraPosition,
meetingLayoutFocusedCamera,
meetingLayoutVideoRate,
meetingPresentationIsOpen,
shouldShowScreenshare,
shouldShowExternalVideo,
enforceLayout,
2024-01-30 21:03:11 +08:00
setLocalSettings,
pushLayoutMeeting,
2022-09-03 02:18:17 +08:00
} = this.props;
const changeLayout = LAYOUT_TYPE[getFromUserSettings('bbb_change_layout', null)];
const defaultLayout = LAYOUT_TYPE[getFromUserSettings('bbb_default_layout', null)];
const enforcedLayout = LAYOUT_TYPE[enforceLayout] || null;
2022-09-03 02:18:17 +08:00
Settings.application.selectedLayout = enforcedLayout
|| changeLayout
|| defaultLayout
|| meetingLayout;
let { selectedLayout } = Settings.application;
2022-09-03 02:18:17 +08:00
if (isMobile()) {
selectedLayout = selectedLayout === 'custom' ? 'smart' : selectedLayout;
Settings.application.selectedLayout = selectedLayout;
}
2023-07-26 00:20:45 +08:00
Session.set('isGridEnabled', selectedLayout === LAYOUT_TYPE.VIDEO_FOCUS);
2024-01-30 21:03:11 +08:00
Settings.save(setLocalSettings);
2022-09-03 02:18:17 +08:00
const shouldOpenPresentation = shouldShowScreenshare || shouldShowExternalVideo;
let presentationIsOpen = !getFromUserSettings('bbb_hide_presentation_on_join', HIDE_PRESENTATION);
presentationIsOpen = pushLayoutMeeting ? meetingPresentationIsOpen : presentationIsOpen;
presentationIsOpen = shouldOpenPresentation || presentationIsOpen;
MediaService.setPresentationIsOpen(layoutContextDispatch, presentationIsOpen);
Session.set('presentationLastState', presentationIsOpen);
2022-09-03 02:18:17 +08:00
if (selectedLayout === 'custom') {
setTimeout(() => {
layoutContextDispatch({
type: ACTIONS.SET_FOCUSED_CAMERA_ID,
value: meetingLayoutFocusedCamera,
});
layoutContextDispatch({
type: ACTIONS.SET_CAMERA_DOCK_POSITION,
2024-04-02 02:48:15 +08:00
value: meetingLayoutCameraPosition || 'contentTop',
2022-09-03 02:18:17 +08:00
});
if (!equalDouble(meetingLayoutVideoRate, 0)) {
let w, h;
if (horizontalPosition) {
w = window.innerWidth * meetingLayoutVideoRate;
h = cameraHeight;
} else {
w = cameraWidth;
h = window.innerHeight * meetingLayoutVideoRate;
}
layoutContextDispatch({
type: ACTIONS.SET_CAMERA_DOCK_SIZE,
value: {
width: w,
height: h,
browserWidth: window.innerWidth,
browserHeight: window.innerHeight,
}
});
}
}, 0);
}
}
componentDidUpdate(prevProps) {
const {
cameraWidth,
cameraHeight,
cameraIsResizing,
cameraPosition,
focusedCamera,
horizontalPosition,
isMeetingLayoutResizing,
2022-09-03 02:18:17 +08:00
isModerator,
isPresenter,
layoutContextDispatch,
meetingLayout,
meetingLayoutUpdatedAt,
meetingPresentationIsOpen,
meetingLayoutCameraPosition,
meetingLayoutFocusedCamera,
meetingLayoutVideoRate,
presentationIsOpen,
presentationVideoRate,
pushLayout,
pushLayoutMeeting,
selectedLayout,
setMeetingLayout,
setPushLayout,
enforceLayout,
2024-01-30 21:03:11 +08:00
setLocalSettings,
2022-09-03 02:18:17 +08:00
} = this.props;
const meetingLayoutDidChange = meetingLayout !== prevProps.meetingLayout;
const pushLayoutMeetingDidChange = pushLayoutMeeting !== prevProps.pushLayoutMeeting;
const enforceLayoutDidChange = enforceLayout !== prevProps.enforceLayout;
2022-09-03 02:18:17 +08:00
const shouldSwitchLayout = isPresenter
? meetingLayoutDidChange || enforceLayoutDidChange
: ((meetingLayoutDidChange || pushLayoutMeetingDidChange) && pushLayoutMeeting) || enforceLayoutDidChange;
2022-09-03 02:18:17 +08:00
if (shouldSwitchLayout) {
let contextLayout = enforceLayout || meetingLayout;
2022-09-03 02:18:17 +08:00
if (isMobile()) {
if (contextLayout === 'custom') {
contextLayout = 'smart';
}
2022-09-03 02:18:17 +08:00
}
layoutContextDispatch({
type: ACTIONS.SET_LAYOUT_TYPE,
value: contextLayout,
});
updateSettings({
application: {
...Settings.application,
selectedLayout: contextLayout,
},
2024-01-30 21:03:11 +08:00
}, null, setLocalSettings);
2022-09-03 02:18:17 +08:00
}
if (!enforceLayout && pushLayoutMeetingDidChange) {
2022-09-03 02:18:17 +08:00
updateSettings({
application: {
...Settings.application,
pushLayout: pushLayoutMeeting,
},
2024-01-30 21:03:11 +08:00
}, null, setLocalSettings);
2022-09-03 02:18:17 +08:00
}
2023-03-17 20:37:45 +08:00
if (meetingLayout === "custom" && selectedLayout === "custom" && !isPresenter) {
2022-09-03 02:18:17 +08:00
if (meetingLayoutFocusedCamera !== prevProps.meetingLayoutFocusedCamera
|| meetingLayoutUpdatedAt !== prevProps.meetingLayoutUpdatedAt) {
layoutContextDispatch({
type: ACTIONS.SET_FOCUSED_CAMERA_ID,
value: meetingLayoutFocusedCamera,
});
}
if (meetingLayoutCameraPosition !== prevProps.meetingLayoutCameraPosition
|| meetingLayoutUpdatedAt !== prevProps.meetingLayoutUpdatedAt) {
layoutContextDispatch({
type: ACTIONS.SET_CAMERA_DOCK_POSITION,
value: meetingLayoutCameraPosition,
});
}
if (!equalDouble(meetingLayoutVideoRate, prevProps.meetingLayoutVideoRate)
|| meetingLayoutUpdatedAt !== prevProps.meetingLayoutUpdatedAt) {
let w, h;
if (horizontalPosition) {
w = window.innerWidth * meetingLayoutVideoRate;
h = cameraHeight;
} else {
w = cameraWidth;
h = window.innerHeight * meetingLayoutVideoRate;
}
if (isMeetingLayoutResizing !== prevProps.isMeetingLayoutResizing) {
2022-09-03 02:18:17 +08:00
layoutContextDispatch({
type: ACTIONS.SET_CAMERA_DOCK_IS_RESIZING,
value: isMeetingLayoutResizing,
2022-09-03 02:18:17 +08:00
});
}
layoutContextDispatch({
type: ACTIONS.SET_CAMERA_DOCK_SIZE,
value: {
width: w,
height: h,
browserWidth: window.innerWidth,
browserHeight: window.innerHeight,
}
});
}
if (meetingPresentationIsOpen !== prevProps.meetingPresentationIsOpen
|| meetingLayoutUpdatedAt !== prevProps.meetingLayoutUpdatedAt) {
layoutContextDispatch({
type: ACTIONS.SET_PRESENTATION_IS_OPEN,
value: meetingPresentationIsOpen,
});
}
}
const layoutChanged = presentationIsOpen !== prevProps.presentationIsOpen
|| selectedLayout !== prevProps.selectedLayout
|| cameraIsResizing !== prevProps.cameraIsResizing
|| cameraPosition !== prevProps.cameraPosition
|| focusedCamera !== prevProps.focusedCamera
|| enforceLayout !== prevProps.enforceLayout
2022-09-03 02:18:17 +08:00
|| !equalDouble(presentationVideoRate, prevProps.presentationVideoRate);
if (pushLayout !== prevProps.pushLayout) { // push layout once after presenter toggles / special case where we set pushLayout to false in all viewers
if (isModerator) {
setPushLayout(pushLayout);
}
}
if (pushLayout && layoutChanged || pushLayout !== prevProps.pushLayout) { // change layout sizes / states
2022-09-03 02:18:17 +08:00
if (isPresenter) {
setMeetingLayout();
}
}
2023-07-26 00:20:45 +08:00
if (selectedLayout !== prevProps.selectedLayout) {
Session.set('isGridEnabled', selectedLayout === LAYOUT_TYPE.VIDEO_FOCUS);
}
2022-09-03 02:18:17 +08:00
}
render() {
return null;
}
};
PushLayoutEngine.propTypes = propTypes;
export default PushLayoutEngine;