123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- import clsx from 'clsx';
- import React, { ReactNode, useEffect, useRef, useState } from 'react';
- import { connect } from 'react-redux';
- import { makeStyles } from 'tss-react/mui';
-
- import { IReduxState } from '../../../../app/types';
- import DeviceStatus from '../../../../prejoin/components/web/preview/DeviceStatus';
- import { isRoomNameEnabled } from '../../../../prejoin/functions.web';
- import Toolbox from '../../../../toolbox/components/web/Toolbox';
- import { isButtonEnabled } from '../../../../toolbox/functions.web';
- import { getConferenceName } from '../../../conference/functions';
- import { PREMEETING_BUTTONS, THIRD_PARTY_PREJOIN_BUTTONS } from '../../../config/constants';
- import { withPixelLineHeight } from '../../../styles/functions.web';
- import Tooltip from '../../../tooltip/components/Tooltip';
- import { isPreCallTestEnabled } from '../../functions';
-
- import ConnectionStatus from './ConnectionStatus';
- import Preview from './Preview';
- import RecordingWarning from './RecordingWarning';
- import UnsafeRoomWarning from './UnsafeRoomWarning';
-
- interface IProps {
-
- /**
- * The list of toolbar buttons to render.
- */
- _buttons: Array<string>;
-
- /**
- * Determine if pre call test is enabled.
- */
- _isPreCallTestEnabled?: boolean;
-
- /**
- * The branding background of the premeeting screen(lobby/prejoin).
- */
- _premeetingBackground: string;
-
- /**
- * The name of the meeting that is about to be joined.
- */
- _roomName: string;
-
- /**
- * Children component(s) to be rendered on the screen.
- */
- children?: ReactNode;
-
- /**
- * Additional CSS class names to set on the icon container.
- */
- className?: string;
-
- /**
- * The name of the participant.
- */
- name?: string;
-
- /**
- * Indicates whether the copy url button should be shown.
- */
- showCopyUrlButton?: boolean;
-
- /**
- * Indicates whether the device status should be shown.
- */
- showDeviceStatus: boolean;
-
- /**
- * Indicates whether to display the recording warning.
- */
- showRecordingWarning?: boolean;
-
- /**
- * If should show unsafe room warning when joining.
- */
- showUnsafeRoomWarning?: boolean;
-
- /**
- * The 'Skip prejoin' button to be rendered (if any).
- */
- skipPrejoinButton?: ReactNode;
-
- /**
- * Whether it's used in the 3rdParty prejoin screen or not.
- */
- thirdParty?: boolean;
-
- /**
- * Title of the screen.
- */
- title?: string;
-
- /**
- * True if the preview overlay should be muted, false otherwise.
- */
- videoMuted?: boolean;
-
- /**
- * The video track to render as preview (if omitted, the default local track will be rendered).
- */
- videoTrack?: Object;
- }
-
- const useStyles = makeStyles()(theme => {
- return {
- container: {
- height: '100%',
- position: 'absolute',
- inset: '0 0 0 0',
- display: 'flex',
- backgroundColor: theme.palette.ui01,
- zIndex: 252,
-
- '@media (max-width: 720px)': {
- flexDirection: 'column-reverse'
- }
- },
- content: {
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- flexShrink: 0,
- boxSizing: 'border-box',
- margin: '0 48px',
- padding: '24px 0 16px',
- position: 'relative',
- width: '300px',
- height: '100%',
- zIndex: 252,
-
- '@media (max-width: 720px)': {
- height: 'auto',
- margin: '0 auto'
- },
-
- // mobile phone landscape
- '@media (max-width: 420px)': {
- padding: '16px 16px 0 16px',
- width: '100%'
- },
-
- '@media (max-width: 400px)': {
- padding: '16px'
- }
- },
- contentControls: {
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- margin: 'auto',
- width: '100%'
- },
- title: {
- ...withPixelLineHeight(theme.typography.heading4),
- color: `${theme.palette.text01}!important`,
- marginBottom: theme.spacing(3),
- textAlign: 'center',
-
- '@media (max-width: 400px)': {
- display: 'none'
- }
- },
- roomNameContainer: {
- width: '100%',
- textAlign: 'center',
- marginBottom: theme.spacing(4)
- },
-
- roomName: {
- ...withPixelLineHeight(theme.typography.heading5),
- color: theme.palette.text01,
- display: 'inline-block',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- maxWidth: '100%',
- }
- };
- });
-
- const PreMeetingScreen = ({
- _buttons,
- _isPreCallTestEnabled,
- _premeetingBackground,
- _roomName,
- children,
- className,
- showDeviceStatus,
- showRecordingWarning,
- showUnsafeRoomWarning,
- skipPrejoinButton,
- title,
- videoMuted,
- videoTrack
- }: IProps) => {
- const { classes } = useStyles();
- const style = _premeetingBackground ? {
- background: _premeetingBackground,
- backgroundPosition: 'center',
- backgroundSize: 'cover'
- } : {};
-
- const roomNameRef = useRef<HTMLSpanElement | null>(null);
- const [ isOverflowing, setIsOverflowing ] = useState(false);
-
- useEffect(() => {
- if (roomNameRef.current) {
- const element = roomNameRef.current;
- const elementStyles = window.getComputedStyle(element);
- const elementWidth = Math.floor(parseFloat(elementStyles.width));
-
- setIsOverflowing(element.scrollWidth > elementWidth + 1);
- }
- }, [ _roomName ]);
-
- return (
- <div className = { clsx('premeeting-screen', classes.container, className) }>
- <div style = { style }>
- <div className = { classes.content }>
- {_isPreCallTestEnabled && <ConnectionStatus />}
-
- <div className = { classes.contentControls }>
- <h1 className = { classes.title }>
- {title}
- </h1>
- {_roomName && (
- <span className = { classes.roomNameContainer }>
- {isOverflowing ? (
- <Tooltip content = { _roomName }>
- <span
- className = { classes.roomName }
- ref = { roomNameRef }>
- {_roomName}
- </span>
- </Tooltip>
- ) : (
- <span
- className = { classes.roomName }
- ref = { roomNameRef }>
- {_roomName}
- </span>
- )}
- </span>
- )}
- {children}
- {_buttons.length && <Toolbox toolbarButtons = { _buttons } />}
- {skipPrejoinButton}
- {showUnsafeRoomWarning && <UnsafeRoomWarning />}
- {showDeviceStatus && <DeviceStatus />}
- {showRecordingWarning && <RecordingWarning />}
- </div>
- </div>
- </div>
- <Preview
- videoMuted = { videoMuted }
- videoTrack = { videoTrack } />
- </div>
- );
- };
-
-
- /**
- * Maps (parts of) the redux state to the React {@code Component} props.
- *
- * @param {Object} state - The redux state.
- * @param {Object} ownProps - The props passed to the component.
- * @returns {Object}
- */
- function mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
- const { hiddenPremeetingButtons } = state['features/base/config'];
- const { toolbarButtons } = state['features/toolbox'];
- const premeetingButtons = (ownProps.thirdParty
- ? THIRD_PARTY_PREJOIN_BUTTONS
- : PREMEETING_BUTTONS).filter((b: any) => !(hiddenPremeetingButtons || []).includes(b));
-
- const { premeetingBackground } = state['features/dynamic-branding'];
-
- return {
- // For keeping backwards compat.: if we pass an empty hiddenPremeetingButtons
- // array through external api, we have all prejoin buttons present on premeeting
- // screen regardless of passed values into toolbarButtons config overwrite.
- // If hiddenPremeetingButtons is missing, we hide the buttons according to
- // toolbarButtons config overwrite.
- _buttons: hiddenPremeetingButtons
- ? premeetingButtons
- : premeetingButtons.filter(b => isButtonEnabled(b, toolbarButtons)),
- _isPreCallTestEnabled: isPreCallTestEnabled(state),
- _premeetingBackground: premeetingBackground,
- _roomName: isRoomNameEnabled(state) ? getConferenceName(state) : ''
- };
- }
-
- export default connect(mapStateToProps)(PreMeetingScreen);
|