Webcam draggable refactoring
This commit is contained in:
parent
f19ba4dda0
commit
68ec6411aa
@ -266,6 +266,9 @@ class App extends Component {
|
||||
className={styles.media}
|
||||
aria-label={intl.formatMessage(intlMessages.mediaLabel)}
|
||||
aria-hidden={this.shouldAriaHide()}
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
{media}
|
||||
{this.renderCaptions()}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import WebcamDraggableOverlay from './webcam-draggable-overlay/component';
|
||||
import WebcamDraggable from './webcam-draggable-overlay/component';
|
||||
|
||||
import { styles } from './styles';
|
||||
|
||||
@ -70,6 +70,9 @@ export default class Media extends Component {
|
||||
id="container"
|
||||
className={cx(styles.container)}
|
||||
ref={this.refContainer}
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={!swapLayout ? contentClassName : overlayClassName}
|
||||
@ -79,10 +82,11 @@ export default class Media extends Component {
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<WebcamDraggableOverlay
|
||||
<WebcamDraggable
|
||||
refMediaContainer={this.refContainer}
|
||||
swapLayout={swapLayout}
|
||||
floatingOverlay={floatingOverlay}
|
||||
singleWebcam={floatingOverlay}
|
||||
usersVideoLenght={usersVideo.length}
|
||||
hideOverlay={hideOverlay}
|
||||
disableVideo={disableVideo}
|
||||
audioModalIsOpen={audioModalIsOpen}
|
||||
|
@ -1,6 +1,14 @@
|
||||
@import "../../stylesheets/variables/_all";
|
||||
@import "../../stylesheets/variables/video";
|
||||
|
||||
.cursorGrab{
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.cursorGrabbing{
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.container {
|
||||
order: 1;
|
||||
flex: 2;
|
||||
@ -22,30 +30,21 @@
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
%overlay {
|
||||
display: flex;
|
||||
border: 0;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
z-index: 2;
|
||||
align-items: center;
|
||||
max-height: var(--video-height);
|
||||
min-height: var(--video-height);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.overlayRelative{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.overlayAbsoluteSingle{
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.overlayAbsoluteMult{
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
.overlay {
|
||||
@extend %overlay;
|
||||
}
|
||||
|
||||
.overlayToTop {
|
||||
@ -61,27 +60,38 @@
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px; width: 1px;
|
||||
margin: -1px; padding: 0; border: 0;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.floatingOverlay {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
@extend %overlay;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
@include mq($medium-up) {
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: fit-content;
|
||||
min-width: calc(var(--video-height) * var(--video-ratio));
|
||||
max-width: fit-content;
|
||||
height: fit-content;
|
||||
min-height: var(--video-height);
|
||||
}
|
||||
}
|
||||
|
||||
.fit {
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
.full {
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
@ -90,14 +100,6 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.dragging {
|
||||
opacity: .5;
|
||||
}
|
||||
@ -110,17 +112,24 @@
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.dropZoneTop {
|
||||
.dropZoneBgTop,
|
||||
.dropZoneBgBottom {
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dropZoneTop,
|
||||
.dropZoneBgTop {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.dropZoneBottom {
|
||||
.dropZoneBottom,
|
||||
.dropZoneBgBottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.dropZoneBg {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
.dropZoneTop:hover .dropZoneBgTop,
|
||||
.dropZoneBottom:hover .dropZoneBgBottom {
|
||||
background-color: rgba(255, 255, 255, .3);
|
||||
}
|
||||
}
|
@ -1,488 +1,212 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import VideoProviderContainer from '/imports/ui/components/video-provider/container';
|
||||
import _ from 'lodash';
|
||||
import browser from 'browser-detect';
|
||||
|
||||
import Draggable from 'react-draggable';
|
||||
|
||||
import cx from 'classnames';
|
||||
import * as _ from 'lodash';
|
||||
import browser from 'browser-detect';
|
||||
import { withDraggableContext } from './context';
|
||||
import VideoProviderContainer from '/imports/ui/components/video-provider/container';
|
||||
import { styles } from '../styles.scss';
|
||||
import Storage from '../../../services/storage/session';
|
||||
|
||||
const propTypes = {
|
||||
floatingOverlay: PropTypes.bool,
|
||||
hideOverlay: PropTypes.bool,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
floatingOverlay: false,
|
||||
hideOverlay: true,
|
||||
};
|
||||
|
||||
const fullscreenChangedEvents = [
|
||||
'fullscreenchange',
|
||||
'webkitfullscreenchange',
|
||||
'mozfullscreenchange',
|
||||
'MSFullscreenChange',
|
||||
];
|
||||
|
||||
const { webcamsDefaultPlacement } = Meteor.settings.public.layout;
|
||||
const BROWSER_ISMOBILE = browser().mobile;
|
||||
|
||||
export default class WebcamDraggableOverlay extends Component {
|
||||
static getWebcamGridBySelector() {
|
||||
return document.querySelector('div[class*="videoList"]');
|
||||
}
|
||||
|
||||
static getVideoCountBySelector() {
|
||||
return document.querySelectorAll('video[class*="media"]').length;
|
||||
}
|
||||
|
||||
static getOverlayBySelector() {
|
||||
return document.querySelector('div[class*="overlay"]');
|
||||
}
|
||||
|
||||
static waitFor(condition, callback) {
|
||||
const cond = condition();
|
||||
if (!cond) {
|
||||
setTimeout(WebcamDraggableOverlay.waitFor.bind(null, condition, callback), 500);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class WebcamDraggable extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dragging: false,
|
||||
showDropZones: false,
|
||||
showBgDropZoneTop: false,
|
||||
showBgDropZoneBottom: false,
|
||||
dropOnTop: true,
|
||||
dropOnBottom: false,
|
||||
initialPosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
initialRectPosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
lastPosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
resetPosition: false,
|
||||
isFullScreen: false,
|
||||
isVideoLoaded: false,
|
||||
isMinWidth: false,
|
||||
};
|
||||
|
||||
this.shouldUpdatePosition = true;
|
||||
|
||||
this.updateWebcamPositionByResize = this.updateWebcamPositionByResize.bind(this);
|
||||
this.eventVideoFocusChangeListener = this.eventVideoFocusChangeListener.bind(this);
|
||||
|
||||
this.eventResizeListener = _.throttle(
|
||||
this.updateWebcamPositionByResize,
|
||||
500,
|
||||
{
|
||||
leading: true,
|
||||
trailing: true,
|
||||
},
|
||||
);
|
||||
|
||||
this.videoMounted = this.videoMounted.bind(this);
|
||||
|
||||
this.handleWebcamDragStart = this.handleWebcamDragStart.bind(this);
|
||||
this.handleWebcamDragStop = this.handleWebcamDragStop.bind(this);
|
||||
this.handleFullscreenChange = this.handleFullscreenChange.bind(this);
|
||||
this.fullscreenButtonChange = this.fullscreenButtonChange.bind(this);
|
||||
|
||||
this.setIsFullScreen = this.setIsFullScreen.bind(this);
|
||||
this.setResetPosition = this.setResetPosition.bind(this);
|
||||
this.setInitialReferencePoint = this.setInitialReferencePoint.bind(this);
|
||||
this.setLastPosition = this.setLastPosition.bind(this);
|
||||
this.setLastWebcamPosition = this.setLastWebcamPosition.bind(this);
|
||||
this.setisMinWidth = this.setisMinWidth.bind(this);
|
||||
this.setDropOnTop = this.setDropOnTop.bind(this);
|
||||
|
||||
this.dropZoneTopEnterHandler = this.dropZoneTopEnterHandler.bind(this);
|
||||
this.dropZoneTopLeaveHandler = this.dropZoneTopLeaveHandler.bind(this);
|
||||
|
||||
this.dropZoneBottomEnterHandler = this.dropZoneBottomEnterHandler.bind(this);
|
||||
this.dropZoneBottomLeaveHandler = this.dropZoneBottomLeaveHandler.bind(this);
|
||||
|
||||
this.dropZoneTopMouseUpHandler = this.dropZoneTopMouseUpHandler.bind(this);
|
||||
this.dropZoneBottomMouseUpHandler = this.dropZoneBottomMouseUpHandler.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { floatingOverlay } = this.props;
|
||||
const { resetPosition } = this.state;
|
||||
|
||||
if (!floatingOverlay
|
||||
&& !resetPosition) {
|
||||
this.setResetPosition(true);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', this.eventResizeListener);
|
||||
window.addEventListener('videoFocusChange', this.eventVideoFocusChangeListener);
|
||||
|
||||
fullscreenChangedEvents.forEach((event) => {
|
||||
document.addEventListener(event, this.handleFullscreenChange);
|
||||
});
|
||||
|
||||
// Ensures that the event will be called before the resize
|
||||
document.addEventListener('webcamFullscreenButtonChange', this.fullscreenButtonChange);
|
||||
window.addEventListener('resize', _.debounce(this.onResize.bind(this), 500));
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { swapLayout, usersVideo, mediaContainer } = this.props;
|
||||
const { lastPosition } = this.state;
|
||||
const { y } = lastPosition;
|
||||
const userLength = usersVideo.length;
|
||||
const prevUserLength = prevProps.usersVideo.length;
|
||||
const { swapLayout } = this.props;
|
||||
if (prevProps.swapLayout === true && swapLayout === false) {
|
||||
setTimeout(() => this.forceUpdate(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
if (prevProps.mediaContainer && mediaContainer) {
|
||||
const mediaContainerRect = mediaContainer.getBoundingClientRect();
|
||||
const {
|
||||
left: mediaLeft,
|
||||
top: mediaTop,
|
||||
} = mediaContainerRect;
|
||||
const prevMediaContainerRect = prevProps.mediaContainer.getBoundingClientRect();
|
||||
const {
|
||||
left: prevMediaLeft,
|
||||
top: prevMediaTop,
|
||||
} = prevMediaContainerRect;
|
||||
onResize() {
|
||||
const { webcamDraggableState, webcamDraggableDispatch } = this.props;
|
||||
const { mediaSize } = webcamDraggableState;
|
||||
const { width: stateWidth, height: stateHeight } = mediaSize;
|
||||
const { width, height } = this.getMediaBounds();
|
||||
|
||||
if (mediaLeft !== prevMediaLeft || mediaTop !== prevMediaTop) {
|
||||
this.shouldUpdatePosition = false;
|
||||
} else if (this.shouldUpdatePosition === false) {
|
||||
this.shouldUpdatePosition = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevProps.swapLayout && !swapLayout && userLength === 1) {
|
||||
this.shouldUpdatePosition = false;
|
||||
}
|
||||
if (prevProps.swapLayout && !swapLayout && userLength > 1) {
|
||||
this.setLastPosition(0, y);
|
||||
}
|
||||
if (prevUserLength === 1 && userLength > 1) {
|
||||
this.setResetPosition(true);
|
||||
this.setDropOnTop(true);
|
||||
}
|
||||
if (prevUserLength !== userLength) {
|
||||
WebcamDraggableOverlay.waitFor(
|
||||
() => WebcamDraggableOverlay.getVideoCountBySelector() === userLength,
|
||||
this.updateWebcamPositionByResize,
|
||||
if (stateWidth !== width || stateHeight !== height) {
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setMediaSize',
|
||||
value: {
|
||||
width,
|
||||
height,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
fullscreenChangedEvents.forEach((event) => {
|
||||
document.removeEventListener(event, this.handleFullscreenChange);
|
||||
});
|
||||
|
||||
document.removeEventListener('webcamFullscreenButtonChange', this.fullscreenButtonChange);
|
||||
document.removeEventListener('videoFocusChange', this.eventVideoFocusChangeListener);
|
||||
}
|
||||
|
||||
setIsFullScreen(isFullScreen) {
|
||||
this.setState({ isFullScreen });
|
||||
}
|
||||
|
||||
setResetPosition(resetPosition) {
|
||||
this.setState({ resetPosition });
|
||||
}
|
||||
|
||||
setLastPosition(x, y) {
|
||||
this.setState({
|
||||
lastPosition: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setDropOnTop(dropOnTop) {
|
||||
this.setState({ dropOnTop });
|
||||
}
|
||||
|
||||
setInitialReferencePoint() {
|
||||
const { refMediaContainer, usersVideo } = this.props;
|
||||
getMediaBounds() {
|
||||
const { refMediaContainer, webcamDraggableState, webcamDraggableDispatch } = this.props;
|
||||
const { mediaSize: mediaState } = webcamDraggableState;
|
||||
const { current: mediaContainer } = refMediaContainer;
|
||||
const userLength = usersVideo.length;
|
||||
|
||||
const webcamBySelector = WebcamDraggableOverlay.getWebcamGridBySelector();
|
||||
|
||||
if (webcamBySelector && mediaContainer && this.shouldUpdatePosition) {
|
||||
const webcamBySelectorRect = webcamBySelector.getBoundingClientRect();
|
||||
const {
|
||||
width: webcamWidth,
|
||||
height: webcamHeight,
|
||||
} = webcamBySelectorRect;
|
||||
|
||||
if (mediaContainer) {
|
||||
const mediaContainerRect = mediaContainer.getBoundingClientRect();
|
||||
const {
|
||||
width: mediaWidth,
|
||||
height: mediaHeight,
|
||||
top, left, width, height,
|
||||
} = mediaContainerRect;
|
||||
|
||||
const x = mediaWidth - ((webcamWidth + 10) * userLength); // 10 is margin
|
||||
const y = mediaHeight - ((webcamHeight + 10)); // 10 is margin
|
||||
if (mediaState.width === 0 || mediaState.height === 0) {
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setMediaSize',
|
||||
value: {
|
||||
width,
|
||||
height,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (x === 0 && y === 0) return false;
|
||||
|
||||
this.setState({
|
||||
initialRectPosition: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setLastWebcamPosition() {
|
||||
const { refMediaContainer, usersVideo, floatingOverlay } = this.props;
|
||||
const { current: mediaContainer } = refMediaContainer;
|
||||
const {
|
||||
initialRectPosition,
|
||||
dragging,
|
||||
dropOnTop,
|
||||
dropOnBottom,
|
||||
} = this.state;
|
||||
const userLength = usersVideo.length;
|
||||
|
||||
const { x: initX, y: initY } = initialRectPosition;
|
||||
const webcamBySelector = WebcamDraggableOverlay.getWebcamGridBySelector();
|
||||
|
||||
if (webcamBySelector && mediaContainer && this.shouldUpdatePosition) {
|
||||
const webcamBySelectorRect = webcamBySelector.getBoundingClientRect();
|
||||
getWebcamsListBounds() {
|
||||
const { webcamDraggableState, singleWebcam } = this.props;
|
||||
const { videoListRef } = webcamDraggableState;
|
||||
if (videoListRef) {
|
||||
const videoListRefRect = videoListRef.getBoundingClientRect();
|
||||
const {
|
||||
left: webcamLeft,
|
||||
top: webcamTop,
|
||||
} = webcamBySelectorRect;
|
||||
|
||||
const mediaContainerRect = mediaContainer.getBoundingClientRect();
|
||||
const {
|
||||
left: mediaLeft,
|
||||
top: mediaTop,
|
||||
} = mediaContainerRect;
|
||||
|
||||
const webcamXByMedia = webcamLeft - mediaLeft;
|
||||
const webcamYByMedia = webcamTop - mediaTop;
|
||||
|
||||
let x = -(initX - webcamXByMedia);
|
||||
x = floatingOverlay ? -((initX - webcamXByMedia) + 10) : x;
|
||||
x = userLength > 1 ? 0 : x;
|
||||
|
||||
x = !dragging && webcamXByMedia < 0 ? -initX : x;
|
||||
|
||||
let y = -(initY - webcamYByMedia);
|
||||
y = webcamYByMedia < 0 ? -initY : y;
|
||||
|
||||
y = userLength > 1 && dropOnTop ? -initY : y;
|
||||
y = userLength > 1 && dropOnBottom ? 0 : y;
|
||||
|
||||
y = y < -initY ? -initY : y;
|
||||
y = y > 0 ? 0 : y;
|
||||
|
||||
this.setLastPosition(x, y);
|
||||
top, left, width, height,
|
||||
} = videoListRefRect;
|
||||
return {
|
||||
top: top - 10, // 10 = margin
|
||||
left: left - (singleWebcam ? 10 : 0), // 10 = margin
|
||||
width: width + (singleWebcam ? 20 : 0), // 20 = margin
|
||||
height: height + 20, // 20 = margin
|
||||
};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setisMinWidth(isMinWidth) {
|
||||
this.setState({ isMinWidth });
|
||||
calculatePosition() {
|
||||
const { top: mediaTop, left: mediaLeft } = this.getMediaBounds();
|
||||
const { top: webcamsListTop, left: webcamsListLeft } = this.getWebcamsListBounds();
|
||||
const x = webcamsListLeft - mediaLeft;
|
||||
const y = webcamsListTop - mediaTop;
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
};
|
||||
}
|
||||
|
||||
videoMounted() {
|
||||
this.setResetPosition(true);
|
||||
WebcamDraggableOverlay.waitFor(this.setInitialReferencePoint, this.setLastWebcamPosition);
|
||||
this.setState({ isVideoLoaded: true });
|
||||
}
|
||||
async handleWebcamDragStart() {
|
||||
const { webcamDraggableDispatch, singleWebcam } = this.props;
|
||||
const { x, y } = await this.calculatePosition();
|
||||
|
||||
fullscreenButtonChange() {
|
||||
this.setIsFullScreen(true);
|
||||
}
|
||||
webcamDraggableDispatch({ type: 'dragStart' });
|
||||
|
||||
updateWebcamPositionByResize() {
|
||||
const {
|
||||
isVideoLoaded,
|
||||
isMinWidth,
|
||||
} = this.state;
|
||||
|
||||
if (isVideoLoaded) {
|
||||
this.setInitialReferencePoint();
|
||||
this.setLastWebcamPosition();
|
||||
}
|
||||
|
||||
if (window.innerWidth < 641) {
|
||||
this.setisMinWidth(true);
|
||||
this.setState({ dropOnTop: true });
|
||||
this.setResetPosition(true);
|
||||
} else if (isMinWidth) {
|
||||
this.setisMinWidth(false);
|
||||
}
|
||||
}
|
||||
|
||||
eventVideoFocusChangeListener() {
|
||||
setTimeout(() => {
|
||||
this.setInitialReferencePoint();
|
||||
this.setLastWebcamPosition();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
handleFullscreenChange() {
|
||||
if (document.fullscreenElement
|
||||
|| document.webkitFullscreenElement
|
||||
|| document.mozFullScreenElement
|
||||
|| document.msFullscreenElement) {
|
||||
window.removeEventListener('resize', this.eventResizeListener);
|
||||
this.setIsFullScreen(true);
|
||||
} else {
|
||||
this.setIsFullScreen(false);
|
||||
window.addEventListener('resize', this.eventResizeListener);
|
||||
}
|
||||
}
|
||||
|
||||
handleWebcamDragStart() {
|
||||
const { floatingOverlay } = this.props;
|
||||
const {
|
||||
dragging,
|
||||
showDropZones,
|
||||
dropOnTop,
|
||||
dropOnBottom,
|
||||
resetPosition,
|
||||
} = this.state;
|
||||
|
||||
if (!floatingOverlay && dropOnTop) WebcamDraggableOverlay.getOverlayBySelector().style.top = 0;
|
||||
|
||||
if (!dragging) this.setState({ dragging: true });
|
||||
if (dropOnTop) this.setState({ dropOnTop: false });
|
||||
if (dropOnBottom) this.setState({ dropOnBottom: false });
|
||||
if (!showDropZones) this.setState({ showDropZones: true });
|
||||
|
||||
if (resetPosition) this.setState({ resetPosition: false });
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setTempPosition',
|
||||
value: {
|
||||
x: singleWebcam ? x : 0,
|
||||
y,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
handleWebcamDragStop(e, position) {
|
||||
const {
|
||||
dragging,
|
||||
showDropZones,
|
||||
} = this.state;
|
||||
|
||||
const { webcamDraggableDispatch, singleWebcam } = this.props;
|
||||
const targetClassname = e.target.className;
|
||||
const { x, y } = position;
|
||||
|
||||
if (dragging) this.setState({ dragging: false });
|
||||
if (showDropZones) this.setState({ showDropZones: false });
|
||||
|
||||
this.setLastPosition(x, y);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}
|
||||
|
||||
dropZoneTopEnterHandler() {
|
||||
const {
|
||||
showBgDropZoneTop,
|
||||
} = this.state;
|
||||
|
||||
if (!showBgDropZoneTop) this.setState({ showBgDropZoneTop: true });
|
||||
}
|
||||
|
||||
dropZoneBottomEnterHandler() {
|
||||
const {
|
||||
showBgDropZoneBottom,
|
||||
} = this.state;
|
||||
|
||||
if (!showBgDropZoneBottom) this.setState({ showBgDropZoneBottom: true });
|
||||
}
|
||||
|
||||
dropZoneTopLeaveHandler() {
|
||||
const {
|
||||
showBgDropZoneTop,
|
||||
} = this.state;
|
||||
|
||||
if (showBgDropZoneTop) this.setState({ showBgDropZoneTop: false });
|
||||
}
|
||||
|
||||
dropZoneBottomLeaveHandler() {
|
||||
const {
|
||||
showBgDropZoneBottom,
|
||||
} = this.state;
|
||||
|
||||
if (showBgDropZoneBottom) this.setState({ showBgDropZoneBottom: false });
|
||||
}
|
||||
|
||||
dropZoneTopMouseUpHandler() {
|
||||
const { dropOnTop } = this.state;
|
||||
if (!dropOnTop) {
|
||||
this.setState({
|
||||
dropOnTop: true,
|
||||
dropOnBottom: false,
|
||||
resetPosition: true,
|
||||
});
|
||||
if (targetClassname.includes('Top')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToTop' });
|
||||
} else if (targetClassname.includes('Bottom')) {
|
||||
webcamDraggableDispatch({ type: 'setplacementToBottom' });
|
||||
} else if (singleWebcam) {
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setLastPosition',
|
||||
value: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
},
|
||||
);
|
||||
webcamDraggableDispatch({ type: 'setplacementToFloating' });
|
||||
}
|
||||
webcamDraggableDispatch({ type: 'dragEnd' });
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
setTimeout(() => this.setLastWebcamPosition(), 500);
|
||||
}
|
||||
|
||||
dropZoneBottomMouseUpHandler() {
|
||||
const { dropOnBottom } = this.state;
|
||||
if (!dropOnBottom) {
|
||||
this.setState({
|
||||
dropOnTop: false,
|
||||
dropOnBottom: true,
|
||||
resetPosition: true,
|
||||
});
|
||||
}
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
setTimeout(() => this.setLastWebcamPosition(), 500);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
webcamDraggableState,
|
||||
singleWebcam,
|
||||
swapLayout,
|
||||
floatingOverlay,
|
||||
hideOverlay,
|
||||
disableVideo,
|
||||
audioModalIsOpen,
|
||||
refMediaContainer,
|
||||
usersVideo,
|
||||
} = this.props;
|
||||
|
||||
const userLength = usersVideo.length;
|
||||
|
||||
const { current: mediaContainer } = refMediaContainer;
|
||||
|
||||
let mediaContainerRect;
|
||||
let mediaHeight;
|
||||
if (mediaContainer) {
|
||||
mediaContainerRect = mediaContainer.getBoundingClientRect();
|
||||
const {
|
||||
height,
|
||||
} = mediaContainerRect;
|
||||
mediaHeight = height;
|
||||
const { dragging, isFullscreen } = webcamDraggableState;
|
||||
let 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;
|
||||
} else if (!dragging && placement === 'floating' && singleWebcam) {
|
||||
position = webcamDraggableState.lastPosition;
|
||||
} else {
|
||||
position = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (swapLayout || isFullscreen || BROWSER_ISMOBILE) {
|
||||
position = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
dragging,
|
||||
showDropZones,
|
||||
showBgDropZoneTop,
|
||||
showBgDropZoneBottom,
|
||||
dropOnTop,
|
||||
dropOnBottom,
|
||||
initialPosition,
|
||||
lastPosition,
|
||||
resetPosition,
|
||||
isFullScreen,
|
||||
isMinWidth,
|
||||
} = this.state;
|
||||
width: mediaWidth,
|
||||
height: mediaHeight,
|
||||
} = this.getMediaBounds();
|
||||
|
||||
const {
|
||||
width: webcamsWidth,
|
||||
height: webcamsHeight,
|
||||
} = this.getWebcamsListBounds();
|
||||
|
||||
const isOverflowWidth = (lastPosition.x + webcamsWidth) > mediaWidth;
|
||||
const isOverflowHeight = (lastPosition.y + webcamsHeight) > mediaHeight;
|
||||
|
||||
position = {
|
||||
x: isOverflowWidth
|
||||
&& !dragging && !swapLayout && singleWebcam && placement === 'floating' ? mediaWidth - webcamsWidth : position.x,
|
||||
y: isOverflowHeight
|
||||
&& !dragging && !swapLayout && singleWebcam && placement === 'floating' ? mediaHeight - (webcamsHeight + 1) : position.y,
|
||||
};
|
||||
|
||||
const contentClassName = cx({
|
||||
[styles.content]: true,
|
||||
@ -490,62 +214,50 @@ export default class WebcamDraggableOverlay extends Component {
|
||||
|
||||
const overlayClassName = cx({
|
||||
[styles.overlay]: true,
|
||||
[styles.overlayRelative]: (dropOnTop || dropOnBottom),
|
||||
[styles.overlayAbsoluteMult]: (!dropOnTop && !dropOnBottom) && userLength > 1,
|
||||
[styles.hideOverlay]: hideOverlay,
|
||||
[styles.floatingOverlay]: floatingOverlay && (!dropOnTop && !dropOnBottom),
|
||||
[styles.overlayToTop]: dropOnTop,
|
||||
[styles.overlayToBottom]: dropOnBottom,
|
||||
[styles.floatingOverlay]: (singleWebcam && placement === 'floating') || dragging,
|
||||
[styles.fit]: singleWebcam && (placement === 'floating' || dragging),
|
||||
[styles.full]: (singleWebcam && (placement === 'top' || placement === 'bottom')
|
||||
&& !dragging)
|
||||
|| !singleWebcam,
|
||||
[styles.overlayToTop]: (placement === 'floating' && !singleWebcam)
|
||||
|| (placement === 'top' && !dragging),
|
||||
[styles.overlayToBottom]: placement === 'bottom' && !dragging,
|
||||
[styles.dragging]: dragging,
|
||||
});
|
||||
|
||||
const dropZoneTopClassName = cx({
|
||||
[styles.dropZoneTop]: true,
|
||||
[styles.show]: showDropZones,
|
||||
[styles.hide]: !showDropZones,
|
||||
[styles.show]: dragging,
|
||||
[styles.hide]: !dragging,
|
||||
[styles.cursorGrabbing]: dragging,
|
||||
});
|
||||
|
||||
const dropZoneBottomClassName = cx({
|
||||
[styles.dropZoneBottom]: true,
|
||||
[styles.show]: showDropZones,
|
||||
[styles.hide]: !showDropZones,
|
||||
[styles.show]: dragging,
|
||||
[styles.hide]: !dragging,
|
||||
[styles.cursorGrabbing]: dragging,
|
||||
});
|
||||
|
||||
const dropZoneBgTopClassName = cx({
|
||||
[styles.dropZoneBg]: true,
|
||||
[styles.top]: true,
|
||||
[styles.show]: showBgDropZoneTop,
|
||||
[styles.hide]: !showBgDropZoneTop,
|
||||
[styles.dropZoneBgTop]: true,
|
||||
});
|
||||
|
||||
const dropZoneBgBottomClassName = cx({
|
||||
[styles.dropZoneBg]: true,
|
||||
[styles.bottom]: true,
|
||||
[styles.show]: showBgDropZoneBottom,
|
||||
[styles.hide]: !showBgDropZoneBottom,
|
||||
[styles.dropZoneBgBottom]: true,
|
||||
});
|
||||
|
||||
const cursor = () => {
|
||||
if ((!swapLayout || !isFullScreen || !BROWSER_ISMOBILE || !isMinWidth) && !dragging) return 'grab';
|
||||
if (dragging) return 'grabbing';
|
||||
return 'default';
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div
|
||||
className={dropZoneTopClassName}
|
||||
onMouseEnter={this.dropZoneTopEnterHandler}
|
||||
onMouseLeave={this.dropZoneTopLeaveHandler}
|
||||
onMouseUp={this.dropZoneTopMouseUpHandler}
|
||||
data-dropzone="dropZoneTop"
|
||||
role="presentation"
|
||||
style={{ height: userLength > 1 ? '50%' : '20%' }}
|
||||
/>
|
||||
<div
|
||||
className={dropZoneBgTopClassName}
|
||||
style={{ height: userLength > 1 ? '50%' : '20%' }}
|
||||
/>
|
||||
style={{ height: !singleWebcam ? '50%' : '20%' }}
|
||||
>
|
||||
<div
|
||||
className={dropZoneBgTopClassName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Draggable
|
||||
handle="video"
|
||||
@ -553,44 +265,41 @@ export default class WebcamDraggableOverlay extends Component {
|
||||
onStart={this.handleWebcamDragStart}
|
||||
onStop={this.handleWebcamDragStop}
|
||||
onMouseDown={e => e.preventDefault()}
|
||||
disabled={swapLayout || isFullScreen || BROWSER_ISMOBILE || isMinWidth}
|
||||
position={resetPosition || swapLayout ? initialPosition : lastPosition}
|
||||
disabled={swapLayout || isFullscreen || BROWSER_ISMOBILE}
|
||||
position={position}
|
||||
>
|
||||
<div
|
||||
className={!swapLayout ? overlayClassName : contentClassName}
|
||||
style={{
|
||||
maxHeight: mediaHeight,
|
||||
marginLeft: singleWebcam
|
||||
&& !(placement === 'bottom' || placement === 'top')
|
||||
? 10
|
||||
: 0,
|
||||
marginRight: singleWebcam
|
||||
&& !(placement === 'bottom' || placement === 'top')
|
||||
? 10
|
||||
: 0,
|
||||
}}
|
||||
>
|
||||
{
|
||||
!disableVideo && !audioModalIsOpen
|
||||
? (
|
||||
<VideoProviderContainer
|
||||
cursor={cursor()}
|
||||
swapLayout={swapLayout}
|
||||
onMount={this.videoMounted}
|
||||
/>
|
||||
) : null}
|
||||
{!disableVideo && !audioModalIsOpen ? (
|
||||
<VideoProviderContainer
|
||||
swapLayout={swapLayout}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</Draggable>
|
||||
|
||||
<div
|
||||
className={dropZoneBottomClassName}
|
||||
onMouseEnter={this.dropZoneBottomEnterHandler}
|
||||
onMouseLeave={this.dropZoneBottomLeaveHandler}
|
||||
onMouseUp={this.dropZoneBottomMouseUpHandler}
|
||||
data-dropzone="dropZoneBottom"
|
||||
role="presentation"
|
||||
style={{ height: userLength > 1 ? '50%' : '20%' }}
|
||||
/>
|
||||
<div
|
||||
className={dropZoneBgBottomClassName}
|
||||
style={{ height: userLength > 1 ? '50%' : '20%' }}
|
||||
/>
|
||||
style={{ height: !singleWebcam ? '50%' : '20%' }}
|
||||
>
|
||||
<div
|
||||
className={dropZoneBgBottomClassName}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WebcamDraggableOverlay.propTypes = propTypes;
|
||||
WebcamDraggableOverlay.defaultProps = defaultProps;
|
||||
export default withDraggableContext(WebcamDraggable);
|
||||
|
@ -0,0 +1,178 @@
|
||||
import React, { createContext, useReducer, useEffect } from 'react';
|
||||
import Storage from '../../../services/storage/session';
|
||||
|
||||
export const WebcamDraggableContext = createContext();
|
||||
|
||||
const initialState = {
|
||||
placement: 'top',
|
||||
mediaSize: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
initialRef: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
tempPosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
lastPosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
dragging: false,
|
||||
videoRef: null,
|
||||
videoListRef: null,
|
||||
isFullscreen: false,
|
||||
};
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'setplacementToTop': {
|
||||
return {
|
||||
...state,
|
||||
placement: 'top',
|
||||
};
|
||||
}
|
||||
case 'setplacementToBottom': {
|
||||
return {
|
||||
...state,
|
||||
placement: 'bottom',
|
||||
};
|
||||
}
|
||||
case 'setplacementToFloating': {
|
||||
return {
|
||||
...state,
|
||||
placement: 'floating',
|
||||
};
|
||||
}
|
||||
case 'setMediaSize': {
|
||||
return {
|
||||
...state,
|
||||
mediaSize: {
|
||||
width: action.value.width,
|
||||
height: action.value.height,
|
||||
},
|
||||
};
|
||||
}
|
||||
case 'setWebcamRef': {
|
||||
return {
|
||||
...state,
|
||||
webcamRef: action.value,
|
||||
};
|
||||
}
|
||||
case 'setInitialRef': {
|
||||
return {
|
||||
...state,
|
||||
initialRef: {
|
||||
x: action.value.x,
|
||||
y: action.value.y,
|
||||
},
|
||||
};
|
||||
}
|
||||
case 'setTempPosition': {
|
||||
return {
|
||||
...state,
|
||||
tempPosition: {
|
||||
x: action.value.x,
|
||||
y: action.value.y,
|
||||
},
|
||||
};
|
||||
}
|
||||
case 'setLastPosition': {
|
||||
return {
|
||||
...state,
|
||||
lastPosition: {
|
||||
x: action.value.x,
|
||||
y: action.value.y,
|
||||
},
|
||||
};
|
||||
}
|
||||
case 'setVideoRef': {
|
||||
return {
|
||||
...state,
|
||||
videoRef: action.value,
|
||||
};
|
||||
}
|
||||
case 'setVideoListRef': {
|
||||
return {
|
||||
...state,
|
||||
videoListRef: action.value,
|
||||
};
|
||||
}
|
||||
case 'dragStart': {
|
||||
return {
|
||||
...state,
|
||||
dragging: true,
|
||||
};
|
||||
}
|
||||
case 'dragEnd': {
|
||||
return {
|
||||
...state,
|
||||
dragging: false,
|
||||
};
|
||||
}
|
||||
case 'onFullscreen': {
|
||||
return {
|
||||
...state,
|
||||
isFullscreen: true,
|
||||
};
|
||||
}
|
||||
case 'offFullscreen': {
|
||||
return {
|
||||
...state,
|
||||
isFullscreen: false,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unexpected action');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const ContextConsumer = Component => props => (
|
||||
<WebcamDraggableContext.Consumer>
|
||||
{contexts => <Component {...props} {...contexts} />}
|
||||
</WebcamDraggableContext.Consumer>
|
||||
);
|
||||
|
||||
const ContextProvider = (props) => {
|
||||
const [webcamDraggableState, webcamDraggableDispatch] = useReducer(reducer, initialState);
|
||||
const { placement, lastPosition } = webcamDraggableState;
|
||||
const { children } = props;
|
||||
useEffect(() => {
|
||||
Storage.setItem('webcamPlacement', placement);
|
||||
Storage.setItem('webcamLastPosition', lastPosition);
|
||||
}, [
|
||||
placement,
|
||||
lastPosition,
|
||||
]);
|
||||
|
||||
return (
|
||||
<WebcamDraggableContext.Provider value={{
|
||||
webcamDraggableState,
|
||||
webcamDraggableDispatch,
|
||||
...props,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WebcamDraggableContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const withProvider = Component => props => (
|
||||
<ContextProvider {...props}>
|
||||
<Component />
|
||||
</ContextProvider>
|
||||
);
|
||||
|
||||
const withConsumer = Component => ContextConsumer(Component);
|
||||
|
||||
const withDraggableContext = Component => withProvider(withConsumer(Component));
|
||||
|
||||
export {
|
||||
withProvider,
|
||||
withConsumer,
|
||||
withDraggableContext,
|
||||
};
|
@ -161,9 +161,6 @@ class VideoProvider extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { onMount } = this.props;
|
||||
onMount();
|
||||
|
||||
this.checkIceConnectivity();
|
||||
document.addEventListener('joinVideo', this.shareWebcam); // TODO find a better way to do this
|
||||
document.addEventListener('exitVideo', this.unshareWebcam);
|
||||
@ -1017,14 +1014,10 @@ class VideoProvider extends Component {
|
||||
const {
|
||||
users,
|
||||
enableVideoStats,
|
||||
cursor,
|
||||
swapLayout,
|
||||
mediaHeight,
|
||||
} = this.props;
|
||||
return (
|
||||
<VideoList
|
||||
cursor={cursor}
|
||||
swapLayout={swapLayout}
|
||||
mediaHeight={mediaHeight}
|
||||
users={users}
|
||||
onMount={this.createVideoTag}
|
||||
|
@ -12,6 +12,7 @@ const VideoProviderContainer = ({ children, ...props }) => {
|
||||
export default withTracker(props => ({
|
||||
cursor: props.cursor,
|
||||
swapLayout: props.swapLayout,
|
||||
mediaHeight: props.mediaHeight,
|
||||
meetingId: VideoService.meetingId(),
|
||||
users: VideoService.getAllUsersVideo(),
|
||||
userId: VideoService.userId(),
|
||||
@ -19,5 +20,4 @@ export default withTracker(props => ({
|
||||
userName: VideoService.userName(),
|
||||
enableVideoStats: getFromUserSettings('enableVideoStats', Meteor.settings.public.kurento.enableVideoStats),
|
||||
voiceBridge: VideoService.voiceBridge(),
|
||||
onMount: props.onMount,
|
||||
}))(VideoProviderContainer);
|
||||
|
@ -5,6 +5,7 @@ import cx from 'classnames';
|
||||
import _ from 'lodash';
|
||||
import { styles } from './styles';
|
||||
import VideoListItem from './video-list-item/component';
|
||||
import { withConsumer } from '../../media/webcam-draggable-overlay/context';
|
||||
|
||||
const propTypes = {
|
||||
users: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
@ -77,6 +78,14 @@ class VideoList extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { webcamDraggableDispatch } = this.props;
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setVideoListRef',
|
||||
value: this.grid,
|
||||
},
|
||||
);
|
||||
|
||||
this.handleCanvasResize();
|
||||
window.addEventListener('resize', this.handleCanvasResize, false);
|
||||
}
|
||||
@ -93,6 +102,7 @@ class VideoList extends Component {
|
||||
}
|
||||
const { focusedId } = this.state;
|
||||
const { width: canvasWidth, height: canvasHeight } = this.canvas.getBoundingClientRect();
|
||||
|
||||
const gridGutter = parseInt(window.getComputedStyle(this.grid)
|
||||
.getPropertyValue('grid-row-gap'), 10);
|
||||
const hasFocusedItem = numItems > 2 && focusedId;
|
||||
@ -142,8 +152,6 @@ class VideoList extends Component {
|
||||
getStats,
|
||||
stopGettingStats,
|
||||
enableVideoStats,
|
||||
cursor,
|
||||
swapLayout,
|
||||
} = this.props;
|
||||
const { focusedId } = this.state;
|
||||
|
||||
@ -167,9 +175,6 @@ class VideoList extends Component {
|
||||
[styles.videoListItem]: true,
|
||||
[styles.focused]: focusedId === user.id && users.length > 2,
|
||||
})}
|
||||
style={{
|
||||
cursor,
|
||||
}}
|
||||
>
|
||||
<VideoListItem
|
||||
numOfUsers={users.length}
|
||||
@ -182,7 +187,6 @@ class VideoList extends Component {
|
||||
getStats={(videoRef, callback) => getStats(user.id, videoRef, callback)}
|
||||
stopGettingStats={() => stopGettingStats(user.id)}
|
||||
enableVideoStats={enableVideoStats}
|
||||
swapLayout={swapLayout}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -231,4 +235,4 @@ class VideoList extends Component {
|
||||
|
||||
VideoList.propTypes = propTypes;
|
||||
|
||||
export default injectIntl(VideoList);
|
||||
export default injectIntl(withConsumer(VideoList));
|
||||
|
@ -39,6 +39,9 @@
|
||||
|
||||
.videoListItem {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&.focused {
|
||||
grid-column: 1 / span 2;
|
||||
@ -50,7 +53,6 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 5px;
|
||||
|
||||
&::after {
|
||||
@ -83,6 +85,14 @@
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.cursorGrab{
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.cursorGrabbing{
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
@ -129,6 +139,7 @@
|
||||
|
||||
.media {
|
||||
@extend %media-area;
|
||||
background-color: var(--color-gray);
|
||||
}
|
||||
|
||||
.info {
|
||||
|
@ -16,6 +16,7 @@ import logger from '/imports/startup/client/logger';
|
||||
import VideoListItemStats from './video-list-item-stats/component';
|
||||
import FullscreenButtonContainer from '../../fullscreen-button/container';
|
||||
import { styles } from '../styles';
|
||||
import { withConsumer } from '../../../media/webcam-draggable-overlay/context';
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
connectionStatsLabel: {
|
||||
@ -40,7 +41,15 @@ class VideoListItem extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { onMount } = this.props;
|
||||
const { onMount, webcamDraggableDispatch } = this.props;
|
||||
|
||||
webcamDraggableDispatch(
|
||||
{
|
||||
type: 'setVideoRef',
|
||||
value: this.videoTag,
|
||||
},
|
||||
);
|
||||
|
||||
onMount(this.videoTag);
|
||||
|
||||
this.videoTag.addEventListener('loadeddata', () => this.setVideoIsReady());
|
||||
@ -130,7 +139,9 @@ class VideoListItem extends Component {
|
||||
render() {
|
||||
const { showStats, stats, videoIsReady } = this.state;
|
||||
const {
|
||||
user, numOfUsers,
|
||||
user,
|
||||
numOfUsers,
|
||||
webcamDraggableState,
|
||||
} = this.props;
|
||||
const availableActions = this.getAvailableActions();
|
||||
const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false;
|
||||
@ -149,6 +160,8 @@ class VideoListItem extends Component {
|
||||
muted
|
||||
className={cx({
|
||||
[styles.media]: true,
|
||||
[styles.cursorGrab]: !webcamDraggableState.dragging,
|
||||
[styles.cursorGrabbing]: webcamDraggableState.dragging,
|
||||
})}
|
||||
ref={(ref) => { this.videoTag = ref; }}
|
||||
autoPlay
|
||||
@ -198,7 +211,7 @@ class VideoListItem extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(VideoListItem);
|
||||
export default injectIntl(withConsumer(VideoListItem));
|
||||
|
||||
VideoListItem.defaultProps = {
|
||||
numOfUsers: 0,
|
||||
|
Loading…
Reference in New Issue
Block a user