bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/video-provider/video-button/component.jsx

200 lines
5.7 KiB
React
Raw Normal View History

import React, { memo } from 'react';
import PropTypes from 'prop-types';
2022-02-15 04:20:50 +08:00
import ButtonEmoji from '/imports/ui/components/common/button/button-emoji/ButtonEmoji';
2019-11-28 21:13:06 +08:00
import VideoService from '../service';
import { defineMessages, injectIntl } from 'react-intl';
import Styled from './styles';
2019-11-28 21:13:06 +08:00
import { validIOSVersion } from '/imports/ui/components/app/service';
import deviceInfo from '/imports/utils/deviceInfo';
2021-02-10 21:29:26 +08:00
import { debounce } from 'lodash';
import BBBMenu from '/imports/ui/components/common/menu/component';
2022-08-26 22:50:46 +08:00
import { isVirtualBackgroundsEnabled } from '/imports/ui/services/features';
2022-06-17 03:59:01 +08:00
import Button from '/imports/ui/components/common/button/component';
2017-09-20 11:12:10 +08:00
const ENABLE_WEBCAM_SELECTOR_BUTTON = Meteor.settings.public.app.enableWebcamSelectorButton;
2022-08-26 22:50:46 +08:00
const ENABLE_CAMERA_BRIGHTNESS = Meteor.settings.public.app.enableCameraBrightness;
2017-09-20 11:12:10 +08:00
const intlMessages = defineMessages({
videoSettings: {
id: 'app.video.videoSettings',
description: 'Open video settings',
},
visualEffects: {
id: 'app.video.visualEffects',
description: 'Visual effects label',
},
joinVideo: {
id: 'app.video.joinVideo',
description: 'Join video button label',
2017-09-20 11:12:10 +08:00
},
2019-12-19 01:44:56 +08:00
leaveVideo: {
id: 'app.video.leaveVideo',
description: 'Leave video button label',
},
advancedVideo: {
id: 'app.video.advancedVideo',
description: 'Open advanced video label',
},
2019-03-29 22:31:56 +08:00
videoLocked: {
id: 'app.video.videoLocked',
description: 'video disabled label',
2018-03-23 01:02:59 +08:00
},
videoConnecting: {
id: 'app.video.connecting',
description: 'video connecting label',
},
camCapReached: {
id: 'app.video.meetingCamCapReached',
description: 'meeting camera cap label',
},
meteorDisconnected: {
2020-09-10 03:31:20 +08:00
id: 'app.video.clientDisconnected',
description: 'Meteor disconnected label',
},
iOSWarning: {
id: 'app.iOSWarning.label',
description: 'message indicating to upgrade ios version',
},
2017-09-20 11:12:10 +08:00
});
2021-02-10 21:29:26 +08:00
const JOIN_VIDEO_DELAY_MILLISECONDS = 500;
const propTypes = {
intl: PropTypes.object.isRequired,
2019-11-28 21:13:06 +08:00
hasVideoStream: PropTypes.bool.isRequired,
status: PropTypes.string.isRequired,
2019-12-19 01:44:56 +08:00
mountVideoPreview: PropTypes.func.isRequired,
};
const JoinVideoButton = ({
intl,
2019-11-28 21:13:06 +08:00
hasVideoStream,
status,
disableReason,
2019-12-19 01:44:56 +08:00
mountVideoPreview,
}) => {
const { isMobile } = deviceInfo;
const isMobileSharingCamera = hasVideoStream && isMobile;
const isDesktopSharingCamera = hasVideoStream && !isMobile;
const shouldEnableWebcamSelectorButton = ENABLE_WEBCAM_SELECTOR_BUTTON
&& isDesktopSharingCamera;
2022-08-26 22:50:46 +08:00
const shouldEnableWebcamVisualEffectsButton =
(isVirtualBackgroundsEnabled() || ENABLE_CAMERA_BRIGHTNESS)
&& hasVideoStream
&& !isMobile;
const exitVideo = () => isDesktopSharingCamera && (!VideoService.isMultipleCamerasEnabled()
|| shouldEnableWebcamSelectorButton);
2019-12-19 01:44:56 +08:00
2021-02-10 21:29:26 +08:00
const handleOnClick = debounce(() => {
if (!validIOSVersion()) {
return VideoService.notify(intl.formatMessage(intlMessages.iOSWarning));
}
switch (status) {
case 'videoConnecting':
VideoService.stopVideo();
break;
case 'connected':
default:
if (exitVideo()) {
VideoService.exitVideo();
} else {
mountVideoPreview(isMobileSharingCamera);
}
2019-12-19 01:44:56 +08:00
}
2021-02-10 21:29:26 +08:00
}, JOIN_VIDEO_DELAY_MILLISECONDS);
2022-10-25 01:20:49 +08:00
const handleOpenAdvancedOptions = (props) => {
mountVideoPreview(isDesktopSharingCamera, props);
};
const getMessageFromStatus = () => {
let statusMessage = status;
if (status !== 'videoConnecting') {
statusMessage = exitVideo() ? 'leaveVideo' : 'joinVideo';
}
return statusMessage;
};
const label = disableReason
? intl.formatMessage(intlMessages[disableReason])
: intl.formatMessage(intlMessages[getMessageFromStatus()]);
const isSharing = hasVideoStream || status === 'videoConnecting';
const renderUserActions = () => {
const actions = [];
if (shouldEnableWebcamSelectorButton) {
actions.push(
{
key: 'advancedVideo',
label: intl.formatMessage(intlMessages.advancedVideo),
onClick: () => handleOpenAdvancedOptions(),
},
);
}
2022-08-26 22:50:46 +08:00
if (shouldEnableWebcamVisualEffectsButton) {
actions.push(
{
key: 'virtualBgSelection',
label: intl.formatMessage(intlMessages.visualEffects),
onClick: () => handleOpenAdvancedOptions({ isVisualEffects: true }),
},
);
}
if (actions.length === 0) return null;
2022-10-25 01:20:49 +08:00
const customStyles = { top: '-3.6rem' };
return (
<BBBMenu
2022-10-25 01:20:49 +08:00
customStyles={!isMobile ? customStyles : null}
trigger={(
<ButtonEmoji
emoji="device_list_selector"
hideLabel
label={intl.formatMessage(intlMessages.videoSettings)}
rotate
2022-10-04 22:21:52 +08:00
tabIndex={0}
/>
)}
actions={actions}
2022-10-25 01:20:49 +08:00
opts={{
id: "video-dropdown-menu",
keepMounted: true,
transitionDuration: 0,
elevation: 3,
getContentAnchorEl: null,
fullwidth: "true",
anchorOrigin: { vertical: 'top', horizontal: 'center' },
transformOrigin: { vertical: 'top', horizontal: 'center'},
}}
/>
);
}
return (
2021-12-10 22:55:37 +08:00
<Styled.OffsetBottom>
2022-06-17 03:59:01 +08:00
<Button
label={label}
data-test={hasVideoStream ? 'leaveVideo' : 'joinVideo'}
onClick={handleOnClick}
hideLabel
color={isSharing ? 'primary' : 'default'}
icon={isSharing ? 'video' : 'video_off'}
ghost={!isSharing}
size="lg"
circle
disabled={!!disableReason}
/>
{renderUserActions()}
2021-12-10 22:55:37 +08:00
</Styled.OffsetBottom>
);
};
JoinVideoButton.propTypes = propTypes;
2019-12-19 01:44:56 +08:00
export default injectIntl(memo(JoinVideoButton));