Detect aspect ratio to autochange webcams placement #8504
This commit is contained in:
parent
822e11fdae
commit
1ae6324392
@ -11,12 +11,12 @@ import AudioManager from '/imports/ui/services/audio-manager';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import Users from '/imports/api/users';
|
||||
import { Session } from 'meteor/session';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import IntlStartup from './intl';
|
||||
import Meetings, { RecordMeetings } from '../../api/meetings';
|
||||
import AppService from '/imports/ui/components/app/service';
|
||||
import Breakouts from '/imports/api/breakouts';
|
||||
import AudioService from '/imports/ui/components/audio/service';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
|
||||
const BREAKOUT_END_NOTIFY_DELAY = 50;
|
||||
|
@ -21,6 +21,7 @@ import LockNotifier from '/imports/ui/components/lock-viewers/notify/container';
|
||||
import PingPongContainer from '/imports/ui/components/ping-pong/container';
|
||||
import MediaService from '/imports/ui/components/media/service';
|
||||
import ManyWebcamsNotifier from '/imports/ui/components/video-provider/many-users-notify/container';
|
||||
import { withDraggableContext } from '../media/webcam-draggable-overlay/context';
|
||||
import { styles } from './styles';
|
||||
|
||||
const MOBILE_MEDIA = 'only screen and (max-width: 40em)';
|
||||
@ -103,6 +104,7 @@ class App extends Component {
|
||||
|
||||
this.handleWindowResize = throttle(this.handleWindowResize).bind(this);
|
||||
this.shouldAriaHide = this.shouldAriaHide.bind(this);
|
||||
this.renderMedia = withDraggableContext(this.renderMedia.bind(this));
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -1,16 +1,15 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import Draggable from 'react-draggable';
|
||||
import cx from 'classnames';
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import Resizable from 're-resizable';
|
||||
import { isMobile, isIPad13 } from 'react-device-detect';
|
||||
import { withDraggableContext } from './context';
|
||||
import { withDraggableConsumer } from './context';
|
||||
import VideoProviderContainer from '/imports/ui/components/video-provider/container';
|
||||
import { styles } from '../styles.scss';
|
||||
import Storage from '../../../services/storage/session';
|
||||
|
||||
const { webcamsDefaultPlacement } = Meteor.settings.public.layout;
|
||||
const BROWSER_ISMOBILE = isMobile || isIPad13;
|
||||
|
||||
const propTypes = {
|
||||
@ -32,7 +31,7 @@ const defaultProps = {
|
||||
};
|
||||
const dispatchResizeEvent = () => window.dispatchEvent(new Event('resize'));
|
||||
|
||||
class WebcamDraggable extends Component {
|
||||
class WebcamDraggable extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -58,17 +57,34 @@ class WebcamDraggable extends Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { swapLayout, webcamDraggableState } = this.props;
|
||||
const { placement } = webcamDraggableState;
|
||||
const { swapLayout, webcamDraggableState, webcamDraggableDispatch } = this.props;
|
||||
const {
|
||||
placement: statePlacement,
|
||||
orientation,
|
||||
lastPlacementLandscape,
|
||||
lastPlacementPortrait,
|
||||
} = webcamDraggableState;
|
||||
const { webcamDraggableState: prevWebcamDraggableState } = prevProps;
|
||||
const { placement: prevPlacement } = prevWebcamDraggableState;
|
||||
const { placement: prevPlacement, orientation: prevOrientation } = prevWebcamDraggableState;
|
||||
if (prevProps.swapLayout !== swapLayout) {
|
||||
setTimeout(() => this.forceUpdate(), 500);
|
||||
}
|
||||
if (prevPlacement !== placement) {
|
||||
if (prevPlacement !== statePlacement) {
|
||||
setTimeout(() => this.forceUpdate(), 200);
|
||||
setTimeout(() => window.dispatchEvent(new Event('resize')), 500);
|
||||
}
|
||||
|
||||
if (prevOrientation !== orientation) {
|
||||
const storagePlacement = Storage.getItem('webcamPlacement');
|
||||
if ((prevOrientation == null || prevOrientation === 'portrait') && orientation === 'landscape') {
|
||||
if (storagePlacement !== lastPlacementLandscape && lastPlacementLandscape === 'top') webcamDraggableDispatch({ type: 'setplacementToTop' });
|
||||
if (storagePlacement !== lastPlacementLandscape && lastPlacementLandscape === 'bottom') webcamDraggableDispatch({ type: 'setplacementToBottom' });
|
||||
}
|
||||
if ((prevOrientation == null || prevOrientation === 'landscape') && orientation === 'portrait') {
|
||||
if (storagePlacement !== lastPlacementPortrait && lastPlacementPortrait === 'left') webcamDraggableDispatch({ type: 'setplacementToLeft' });
|
||||
if (storagePlacement !== lastPlacementPortrait && lastPlacementPortrait === 'right') webcamDraggableDispatch({ type: 'setplacementToRight' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -227,12 +243,16 @@ class WebcamDraggable extends Component {
|
||||
if (targetClassname) {
|
||||
if (targetClassname.includes('Top')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToTop' });
|
||||
webcamDraggableDispatch({ type: 'setLastPlacementLandscapeToTop' });
|
||||
} else if (targetClassname.includes('Right')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToRight' });
|
||||
webcamDraggableDispatch({ type: 'setLastPlacementPortraitToRight' });
|
||||
} else if (targetClassname.includes('Bottom')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToBottom' });
|
||||
webcamDraggableDispatch({ type: 'setLastPlacementLandscapeToBottom' });
|
||||
} else if (targetClassname.includes('Left')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToLeft' });
|
||||
webcamDraggableDispatch({ type: 'setLastPlacementPortraitToLeft' });
|
||||
}
|
||||
}
|
||||
webcamDraggableDispatch({ type: 'dragEnd' });
|
||||
@ -261,12 +281,12 @@ class WebcamDraggable extends Component {
|
||||
videoListSize,
|
||||
optimalGrid,
|
||||
} = webcamDraggableState;
|
||||
let placement = Storage.getItem('webcamPlacement');
|
||||
|
||||
const placement = Storage.getItem('webcamPlacement');
|
||||
|
||||
const lastPosition = Storage.getItem('webcamLastPosition') || { x: 0, y: 0 };
|
||||
|
||||
let position = lastPosition;
|
||||
if (!placement) {
|
||||
placement = webcamsDefaultPlacement;
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
position = webcamDraggableState.tempPosition;
|
||||
@ -537,4 +557,4 @@ class WebcamDraggable extends Component {
|
||||
WebcamDraggable.propTypes = propTypes;
|
||||
WebcamDraggable.defaultProps = defaultProps;
|
||||
|
||||
export default withDraggableContext(WebcamDraggable);
|
||||
export default withDraggableConsumer(WebcamDraggable);
|
||||
|
@ -1,10 +1,15 @@
|
||||
import React, { createContext, useReducer, useEffect } from 'react';
|
||||
import Storage from '../../../services/storage/session';
|
||||
|
||||
const { webcamsDefaultPlacement } = Meteor.settings.public.layout;
|
||||
|
||||
export const WebcamDraggableContext = createContext();
|
||||
|
||||
const initialState = {
|
||||
placement: 'top',
|
||||
placement: webcamsDefaultPlacement,
|
||||
lastPlacementLandscape: 'top',
|
||||
lastPlacementPortrait: 'left',
|
||||
orientation: null,
|
||||
mediaSize: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
@ -58,12 +63,48 @@ const reducer = (state, action) => {
|
||||
placement: 'left',
|
||||
};
|
||||
}
|
||||
case 'setLastPlacementPortraitToLeft': {
|
||||
return {
|
||||
...state,
|
||||
lastPlacementPortrait: 'left',
|
||||
};
|
||||
}
|
||||
case 'setLastPlacementPortraitToRight': {
|
||||
return {
|
||||
...state,
|
||||
lastPlacementPortrait: 'right',
|
||||
};
|
||||
}
|
||||
case 'setLastPlacementLandscapeToTop': {
|
||||
return {
|
||||
...state,
|
||||
lastPlacementLandscape: 'top',
|
||||
};
|
||||
}
|
||||
case 'setLastPlacementLandscapeToBottom': {
|
||||
return {
|
||||
...state,
|
||||
lastPlacementLandscape: 'bottom',
|
||||
};
|
||||
}
|
||||
case 'setplacementToFloating': {
|
||||
return {
|
||||
...state,
|
||||
placement: 'floating',
|
||||
};
|
||||
}
|
||||
case 'setOrientationToLandscape': {
|
||||
return {
|
||||
...state,
|
||||
orientation: 'landscape',
|
||||
};
|
||||
}
|
||||
case 'setOrientationToPortrait': {
|
||||
return {
|
||||
...state,
|
||||
orientation: 'portrait',
|
||||
};
|
||||
}
|
||||
case 'setMediaSize': {
|
||||
return {
|
||||
...state,
|
||||
@ -165,13 +206,22 @@ const ContextConsumer = Component => props => (
|
||||
|
||||
const ContextProvider = (props) => {
|
||||
const [webcamDraggableState, webcamDraggableDispatch] = useReducer(reducer, initialState);
|
||||
const { placement, lastPosition } = webcamDraggableState;
|
||||
const {
|
||||
placement,
|
||||
lastPosition,
|
||||
lastPlacementLandscape,
|
||||
lastPlacementPortrait,
|
||||
} = webcamDraggableState;
|
||||
const { children } = props;
|
||||
useEffect(() => {
|
||||
Storage.setItem('webcamPlacement', placement);
|
||||
Storage.setItem('webcamLastPlacementLandscape', lastPlacementLandscape);
|
||||
Storage.setItem('webcamlastPlacementPortrait', lastPlacementPortrait);
|
||||
Storage.setItem('webcamLastPosition', lastPosition);
|
||||
}, [
|
||||
placement,
|
||||
lastPlacementLandscape,
|
||||
lastPlacementPortrait,
|
||||
lastPosition,
|
||||
]);
|
||||
|
||||
|
@ -15,6 +15,7 @@ import PresentationCloseButton from './presentation-close-button/component';
|
||||
import DownloadPresentationButton from './download-presentation-button/component';
|
||||
import FullscreenService from '../fullscreen-button/service';
|
||||
import FullscreenButtonContainer from '../fullscreen-button/container';
|
||||
import { withDraggableContext, withDraggableConsumer } from '../media/webcam-draggable-overlay/context';
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
presentationLabel: {
|
||||
@ -81,10 +82,25 @@ class PresentationArea extends PureComponent {
|
||||
window.addEventListener('resize', this.onResize);
|
||||
this.getInitialPresentationSizes();
|
||||
this.refPresentationContainer.addEventListener('fullscreenchange', this.onFullscreenChange);
|
||||
|
||||
const { slidePosition, webcamDraggableDispatch } = this.props;
|
||||
const { width: currWidth, height: currHeight } = slidePosition;
|
||||
if (currWidth > currHeight || currWidth === currHeight) {
|
||||
webcamDraggableDispatch({ type: 'setOrientationToLandscape' });
|
||||
}
|
||||
if (currHeight > currWidth) {
|
||||
webcamDraggableDispatch({ type: 'setOrientationToPortrait' });
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { currentPresentation, notify, intl } = this.props;
|
||||
const {
|
||||
currentPresentation,
|
||||
notify,
|
||||
intl,
|
||||
slidePosition,
|
||||
webcamDraggableDispatch,
|
||||
} = this.props;
|
||||
|
||||
if (prevProps.currentPresentation.name !== currentPresentation.name) {
|
||||
notify(
|
||||
@ -93,6 +109,18 @@ class PresentationArea extends PureComponent {
|
||||
'presentation',
|
||||
);
|
||||
}
|
||||
|
||||
const { width: prevWidth, height: prevHeight } = prevProps.slidePosition;
|
||||
const { width: currWidth, height: currHeight } = slidePosition;
|
||||
|
||||
if (prevWidth !== currWidth || prevHeight !== currHeight) {
|
||||
if (currWidth > currHeight || currWidth === currHeight) {
|
||||
webcamDraggableDispatch({ type: 'setOrientationToLandscape' });
|
||||
}
|
||||
if (currHeight > currWidth) {
|
||||
webcamDraggableDispatch({ type: 'setOrientationToPortrait' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -654,7 +682,7 @@ class PresentationArea extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(PresentationArea);
|
||||
export default injectIntl(withDraggableConsumer(PresentationArea));
|
||||
|
||||
PresentationArea.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
|
Loading…
Reference in New Issue
Block a user