2017-11-17 19:06:47 +00:00
|
|
|
// @flow
|
|
|
|
|
2019-03-20 20:09:23 +00:00
|
|
|
import React from 'react';
|
2022-03-29 11:37:32 +00:00
|
|
|
import { BackHandler, NativeModules, SafeAreaView, StatusBar, View } from 'react-native';
|
2022-01-13 12:15:53 +00:00
|
|
|
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2020-06-04 14:09:13 +00:00
|
|
|
import { appNavigate } from '../../../app/actions';
|
2021-03-08 21:11:39 +00:00
|
|
|
import { PIP_ENABLED, FULLSCREEN_ENABLED, getFeatureFlag } from '../../../base/flags';
|
2022-04-06 12:06:48 +00:00
|
|
|
import { getParticipantCount } from '../../../base/participants';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { Container, LoadingIndicator, TintedView } from '../../../base/react';
|
2019-05-23 11:29:40 +00:00
|
|
|
import { connect } from '../../../base/redux';
|
2020-06-02 09:03:17 +00:00
|
|
|
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { TestConnectionInfo } from '../../../base/testing';
|
2019-05-28 13:32:29 +00:00
|
|
|
import { ConferenceNotification, isCalendarEnabled } from '../../../calendar-sync';
|
2019-04-11 10:04:50 +00:00
|
|
|
import { DisplayNameLabel } from '../../../display-name';
|
2018-09-13 15:20:22 +00:00
|
|
|
import {
|
2019-03-20 20:09:23 +00:00
|
|
|
FILMSTRIP_SIZE,
|
2018-09-13 15:20:22 +00:00
|
|
|
Filmstrip,
|
|
|
|
isFilmstripVisible,
|
|
|
|
TileView
|
2019-01-30 13:05:35 +00:00
|
|
|
} from '../../../filmstrip';
|
2021-10-20 19:29:21 +00:00
|
|
|
import { CalleeInfoContainer } from '../../../invite';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { LargeVideo } from '../../../large-video';
|
2022-01-20 14:26:03 +00:00
|
|
|
import { KnockingParticipantList } from '../../../lobby/components/native';
|
2021-08-20 08:53:11 +00:00
|
|
|
import { getIsLobbyVisible } from '../../../lobby/functions';
|
2022-01-25 12:55:57 +00:00
|
|
|
import { navigate }
|
|
|
|
from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef';
|
|
|
|
import { screen } from '../../../mobile/navigation/routes';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { Captions } from '../../../subtitles';
|
2020-07-24 12:14:33 +00:00
|
|
|
import { setToolboxVisible } from '../../../toolbox/actions';
|
|
|
|
import { Toolbox } from '../../../toolbox/components/native';
|
|
|
|
import { isToolboxVisible } from '../../../toolbox/functions';
|
2019-03-20 20:09:23 +00:00
|
|
|
import {
|
|
|
|
AbstractConference,
|
|
|
|
abstractMapStateToProps
|
|
|
|
} from '../AbstractConference';
|
2020-05-20 10:57:03 +00:00
|
|
|
import type { AbstractProps } from '../AbstractConference';
|
|
|
|
|
2022-01-13 12:15:53 +00:00
|
|
|
import AlwaysOnLabels from './AlwaysOnLabels';
|
|
|
|
import ExpandedLabelPopup from './ExpandedLabelPopup';
|
2020-03-20 17:30:46 +00:00
|
|
|
import LonelyMeetingExperience from './LonelyMeetingExperience';
|
2022-01-13 12:15:53 +00:00
|
|
|
import TitleBar from './TitleBar';
|
|
|
|
import { EXPANDED_LABEL_TIMEOUT } from './constants';
|
2021-03-18 10:54:49 +00:00
|
|
|
import styles from './styles';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-02-07 22:52:31 +00:00
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-11-17 19:06:47 +00:00
|
|
|
* The type of the React {@code Component} props of {@link Conference}.
|
2016-10-05 14:36:59 +00:00
|
|
|
*/
|
2019-02-07 22:52:31 +00:00
|
|
|
type Props = AbstractProps & {
|
2017-11-13 15:54:04 +00:00
|
|
|
|
2020-06-02 09:03:17 +00:00
|
|
|
/**
|
|
|
|
* Application's aspect ratio.
|
|
|
|
*/
|
|
|
|
_aspectRatio: Symbol,
|
|
|
|
|
2019-05-28 13:32:29 +00:00
|
|
|
/**
|
|
|
|
* Wherther the calendar feature is enabled or not.
|
|
|
|
*/
|
|
|
|
_calendarEnabled: boolean,
|
|
|
|
|
2016-12-01 01:52:39 +00:00
|
|
|
/**
|
2017-11-13 15:54:04 +00:00
|
|
|
* The indicator which determines that we are still connecting to the
|
|
|
|
* conference which includes establishing the XMPP connection and then
|
2018-08-31 20:06:48 +00:00
|
|
|
* joining the room. If truthy, then an activity/loading indicator will be
|
|
|
|
* rendered.
|
2016-12-01 01:52:39 +00:00
|
|
|
*/
|
2017-11-13 15:54:04 +00:00
|
|
|
_connecting: boolean,
|
2017-09-14 10:18:47 +00:00
|
|
|
|
2018-08-29 19:04:05 +00:00
|
|
|
/**
|
|
|
|
* Set to {@code true} when the filmstrip is currently visible.
|
|
|
|
*/
|
|
|
|
_filmstripVisible: boolean,
|
|
|
|
|
2021-03-08 21:11:39 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines whether fullscreen (immersive) mode is enabled.
|
|
|
|
*/
|
|
|
|
_fullscreenEnabled: boolean,
|
|
|
|
|
2022-04-06 12:06:48 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines if the conference type is one to one.
|
|
|
|
*/
|
|
|
|
_isOneToOneConference: boolean,
|
|
|
|
|
2021-06-11 13:15:44 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines if the participants pane is open.
|
|
|
|
*/
|
2021-06-29 14:05:11 +00:00
|
|
|
_isParticipantsPaneOpen: boolean,
|
2021-06-11 13:12:00 +00:00
|
|
|
|
2019-04-11 10:04:50 +00:00
|
|
|
/**
|
2021-11-04 21:10:43 +00:00
|
|
|
* The ID of the participant currently on stage (if any).
|
2019-04-11 10:04:50 +00:00
|
|
|
*/
|
|
|
|
_largeVideoParticipantId: string,
|
|
|
|
|
2018-05-17 13:23:11 +00:00
|
|
|
/**
|
2019-05-23 11:29:40 +00:00
|
|
|
* Whether Picture-in-Picture is enabled.
|
2018-05-17 13:23:11 +00:00
|
|
|
*/
|
2019-05-23 11:29:40 +00:00
|
|
|
_pictureInPictureEnabled: boolean,
|
2018-05-17 13:23:11 +00:00
|
|
|
|
2018-02-02 13:41:30 +00:00
|
|
|
/**
|
2018-02-13 19:14:06 +00:00
|
|
|
* The indicator which determines whether the UI is reduced (to accommodate
|
|
|
|
* smaller display areas).
|
2018-02-02 13:41:30 +00:00
|
|
|
*/
|
|
|
|
_reducedUI: boolean,
|
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines whether the Toolbox is visible.
|
|
|
|
*/
|
2018-04-16 15:06:11 +00:00
|
|
|
_toolboxVisible: boolean,
|
|
|
|
|
2021-08-20 08:53:11 +00:00
|
|
|
/**
|
|
|
|
* Indicates whether the lobby screen should be visible.
|
|
|
|
*/
|
|
|
|
_showLobby: boolean,
|
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
/**
|
|
|
|
* The redux {@code dispatch} function.
|
|
|
|
*/
|
2022-01-13 12:15:53 +00:00
|
|
|
dispatch: Function,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Object containing the safe area insets.
|
|
|
|
*/
|
|
|
|
insets: Object
|
2017-11-13 15:54:04 +00:00
|
|
|
};
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2022-01-13 12:15:53 +00:00
|
|
|
type State = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The label that is currently expanded.
|
|
|
|
*/
|
|
|
|
visibleExpandedLabel: ?string
|
|
|
|
}
|
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
|
|
|
* The conference page of the mobile (i.e. React Native) application.
|
|
|
|
*/
|
2022-01-13 12:15:53 +00:00
|
|
|
class Conference extends AbstractConference<Props, State> {
|
|
|
|
/**
|
|
|
|
* Timeout ref.
|
|
|
|
*/
|
|
|
|
_expandedLabelTimeout: Object;
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
|
|
|
* Initializes a new Conference instance.
|
|
|
|
*
|
|
|
|
* @param {Object} props - The read-only properties with which the new
|
|
|
|
* instance is to be initialized.
|
|
|
|
*/
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
2022-01-13 12:15:53 +00:00
|
|
|
this.state = {
|
|
|
|
visibleExpandedLabel: undefined
|
|
|
|
};
|
|
|
|
|
|
|
|
this._expandedLabelTimeout = React.createRef();
|
|
|
|
|
2017-09-25 17:26:15 +00:00
|
|
|
// Bind event handlers so they are only bound once per instance.
|
2016-10-05 14:36:59 +00:00
|
|
|
this._onClick = this._onClick.bind(this);
|
2019-05-23 11:29:40 +00:00
|
|
|
this._onHardwareBackPress = this._onHardwareBackPress.bind(this);
|
|
|
|
this._setToolboxVisible = this._setToolboxVisible.bind(this);
|
2022-01-13 12:15:53 +00:00
|
|
|
this._createOnPress = this._createOnPress.bind(this);
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-03 21:06:47 +00:00
|
|
|
/**
|
2017-09-25 17:26:15 +00:00
|
|
|
* Implements {@link Component#componentDidMount()}. Invoked immediately
|
|
|
|
* after this component is mounted.
|
2017-01-03 21:06:47 +00:00
|
|
|
*
|
2017-01-03 21:09:52 +00:00
|
|
|
* @inheritdoc
|
2017-11-03 20:14:38 +00:00
|
|
|
* @returns {void}
|
2017-01-03 21:06:47 +00:00
|
|
|
*/
|
|
|
|
componentDidMount() {
|
2022-03-29 11:37:32 +00:00
|
|
|
BackHandler.addEventListener('hardwareBackPress', this._onHardwareBackPress);
|
2018-05-17 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
2021-10-20 19:29:21 +00:00
|
|
|
/**
|
|
|
|
* Implements {@code Component#componentDidUpdate}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
componentDidUpdate(prevProps) {
|
|
|
|
const { _showLobby } = this.props;
|
|
|
|
|
|
|
|
if (!prevProps._showLobby && _showLobby) {
|
|
|
|
navigate(screen.lobby);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prevProps._showLobby && !_showLobby) {
|
|
|
|
navigate(screen.conference.main);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-09-25 17:26:15 +00:00
|
|
|
* Implements {@link Component#componentWillUnmount()}. Invoked immediately
|
|
|
|
* before this component is unmounted and destroyed. Disconnects the
|
|
|
|
* conference described by the redux store/state.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
componentWillUnmount() {
|
2017-09-25 17:26:15 +00:00
|
|
|
// Tear handling any hardware button presses for back navigation down.
|
2022-03-29 11:37:32 +00:00
|
|
|
BackHandler.removeEventListener('hardwareBackPress', this._onHardwareBackPress);
|
2022-01-13 12:15:53 +00:00
|
|
|
|
|
|
|
clearTimeout(this._expandedLabelTimeout.current);
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render() {
|
2021-10-20 19:29:21 +00:00
|
|
|
const { _fullscreenEnabled } = this.props;
|
2021-03-08 21:11:39 +00:00
|
|
|
|
2019-10-11 13:33:07 +00:00
|
|
|
return (
|
|
|
|
<Container style = { styles.conference }>
|
|
|
|
<StatusBar
|
|
|
|
barStyle = 'light-content'
|
2021-03-08 21:11:39 +00:00
|
|
|
hidden = { _fullscreenEnabled }
|
|
|
|
translucent = { _fullscreenEnabled } />
|
2019-10-11 13:33:07 +00:00
|
|
|
{ this._renderContent() }
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_onClick: () => void;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Changes the value of the toolboxVisible state, thus allowing us to switch
|
|
|
|
* between Toolbox and Filmstrip and change their visibility.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_onClick() {
|
|
|
|
this._setToolboxVisible(!this.props._toolboxVisible);
|
|
|
|
}
|
|
|
|
|
|
|
|
_onHardwareBackPress: () => boolean;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles a hardware button press for back navigation. Enters Picture-in-Picture mode
|
|
|
|
* (if supported) or leaves the associated {@code Conference} otherwise.
|
|
|
|
*
|
|
|
|
* @returns {boolean} Exiting the app is undesired, so {@code true} is always returned.
|
|
|
|
*/
|
|
|
|
_onHardwareBackPress() {
|
|
|
|
let p;
|
|
|
|
|
|
|
|
if (this.props._pictureInPictureEnabled) {
|
|
|
|
const { PictureInPicture } = NativeModules;
|
|
|
|
|
|
|
|
p = PictureInPicture.enterPictureInPicture();
|
|
|
|
} else {
|
|
|
|
p = Promise.reject(new Error('PiP not enabled'));
|
|
|
|
}
|
|
|
|
|
|
|
|
p.catch(() => {
|
|
|
|
this.props.dispatch(appNavigate(undefined));
|
|
|
|
});
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders the conference notification badge if the feature is enabled.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {React$Node}
|
|
|
|
*/
|
|
|
|
_renderConferenceNotification() {
|
|
|
|
const { _calendarEnabled, _reducedUI } = this.props;
|
|
|
|
|
|
|
|
return (
|
|
|
|
_calendarEnabled && !_reducedUI
|
|
|
|
? <ConferenceNotification />
|
|
|
|
: undefined);
|
|
|
|
}
|
|
|
|
|
2022-01-13 12:15:53 +00:00
|
|
|
_createOnPress: (string) => void;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a function to be invoked when the onPress of the touchables are
|
|
|
|
* triggered.
|
|
|
|
*
|
|
|
|
* @param {string} label - The identifier of the label that's onLayout is
|
|
|
|
* triggered.
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
|
|
|
_createOnPress(label) {
|
|
|
|
return () => {
|
|
|
|
const { visibleExpandedLabel } = this.state;
|
|
|
|
|
|
|
|
const newVisibleExpandedLabel
|
|
|
|
= visibleExpandedLabel === label ? undefined : label;
|
|
|
|
|
|
|
|
clearTimeout(this._expandedLabelTimeout.current);
|
|
|
|
this.setState({
|
|
|
|
visibleExpandedLabel: newVisibleExpandedLabel
|
|
|
|
});
|
|
|
|
|
|
|
|
if (newVisibleExpandedLabel) {
|
|
|
|
this._expandedLabelTimeout.current = setTimeout(() => {
|
|
|
|
this.setState({
|
|
|
|
visibleExpandedLabel: undefined
|
|
|
|
});
|
|
|
|
}, EXPANDED_LABEL_TIMEOUT);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-10-11 13:33:07 +00:00
|
|
|
/**
|
|
|
|
* Renders the content for the Conference container.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {React$Element}
|
|
|
|
*/
|
|
|
|
_renderContent() {
|
2018-09-13 15:20:22 +00:00
|
|
|
const {
|
|
|
|
_connecting,
|
2022-04-06 12:06:48 +00:00
|
|
|
_isOneToOneConference,
|
2019-04-11 10:04:50 +00:00
|
|
|
_largeVideoParticipantId,
|
2018-09-13 15:20:22 +00:00
|
|
|
_reducedUI,
|
2021-11-25 16:41:03 +00:00
|
|
|
_shouldDisplayTileView,
|
|
|
|
_toolboxVisible
|
2018-09-13 15:20:22 +00:00
|
|
|
} = this.props;
|
|
|
|
|
2019-10-11 13:33:07 +00:00
|
|
|
if (_reducedUI) {
|
|
|
|
return this._renderContentForReducedUi();
|
|
|
|
}
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-10-11 13:33:07 +00:00
|
|
|
return (
|
|
|
|
<>
|
2017-05-24 17:01:46 +00:00
|
|
|
{/*
|
|
|
|
* The LargeVideo is the lowermost stacking layer.
|
2018-09-13 15:20:22 +00:00
|
|
|
*/
|
|
|
|
_shouldDisplayTileView
|
|
|
|
? <TileView onClick = { this._onClick } />
|
|
|
|
: <LargeVideo onClick = { this._onClick } />
|
|
|
|
}
|
2016-12-12 01:02:50 +00:00
|
|
|
|
2017-11-23 16:26:47 +00:00
|
|
|
{/*
|
|
|
|
* If there is a ringing call, show the callee's info.
|
2018-02-02 13:41:30 +00:00
|
|
|
*/
|
2019-10-11 13:33:07 +00:00
|
|
|
<CalleeInfoContainer />
|
2018-02-02 13:41:30 +00:00
|
|
|
}
|
2017-11-23 16:26:47 +00:00
|
|
|
|
2017-09-14 10:18:47 +00:00
|
|
|
{/*
|
|
|
|
* The activity/loading indicator goes above everything, except
|
|
|
|
* the toolbox/toolbars and the dialogs.
|
|
|
|
*/
|
2018-09-13 15:20:22 +00:00
|
|
|
_connecting
|
2017-12-14 15:04:35 +00:00
|
|
|
&& <TintedView>
|
2017-10-02 23:08:07 +00:00
|
|
|
<LoadingIndicator />
|
2017-12-14 15:04:35 +00:00
|
|
|
</TintedView>
|
2017-09-14 10:18:47 +00:00
|
|
|
}
|
|
|
|
|
2021-03-18 11:32:33 +00:00
|
|
|
<View
|
2018-04-05 19:46:31 +00:00
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = { styles.toolboxAndFilmstripContainer }>
|
2018-08-23 19:57:12 +00:00
|
|
|
|
|
|
|
<Captions onPress = { this._onClick } />
|
|
|
|
|
2022-04-06 12:06:48 +00:00
|
|
|
{
|
|
|
|
_shouldDisplayTileView || (
|
|
|
|
!_isOneToOneConference
|
|
|
|
&& <Container style = { styles.displayNameContainer }>
|
|
|
|
<DisplayNameLabel
|
|
|
|
participantId = { _largeVideoParticipantId } />
|
|
|
|
</Container>
|
|
|
|
)
|
|
|
|
}
|
2019-01-28 14:55:37 +00:00
|
|
|
|
2020-03-20 17:30:46 +00:00
|
|
|
<LonelyMeetingExperience />
|
|
|
|
|
2021-05-07 07:58:57 +00:00
|
|
|
{ _shouldDisplayTileView || <><Filmstrip /><Toolbox /></> }
|
2021-03-18 11:32:33 +00:00
|
|
|
</View>
|
2018-08-31 20:06:48 +00:00
|
|
|
|
2019-03-20 20:09:23 +00:00
|
|
|
<SafeAreaView
|
|
|
|
pointerEvents = 'box-none'
|
2021-11-25 16:41:03 +00:00
|
|
|
style = {
|
|
|
|
_toolboxVisible
|
2022-01-13 12:15:53 +00:00
|
|
|
? styles.titleBarSafeViewColor
|
|
|
|
: styles.titleBarSafeViewTransparent }>
|
|
|
|
<TitleBar _createOnPress = { this._createOnPress } />
|
|
|
|
</SafeAreaView>
|
|
|
|
<SafeAreaView
|
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = {
|
|
|
|
_toolboxVisible
|
|
|
|
? [ styles.titleBarSafeViewTransparent, { top: this.props.insets.top + 50 } ]
|
|
|
|
: styles.titleBarSafeViewTransparent
|
|
|
|
}>
|
|
|
|
<View
|
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = { styles.expandedLabelWrapper }>
|
|
|
|
<ExpandedLabelPopup visibleExpandedLabel = { this.state.visibleExpandedLabel } />
|
|
|
|
</View>
|
|
|
|
<View
|
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = { styles.alwaysOnTitleBar }>
|
|
|
|
{/* eslint-disable-next-line react/jsx-no-bind */}
|
|
|
|
<AlwaysOnLabels createOnPress = { this._createOnPress } />
|
|
|
|
</View>
|
|
|
|
{this._renderNotificationsContainer()}
|
2020-04-15 13:13:43 +00:00
|
|
|
<KnockingParticipantList />
|
2019-03-20 20:09:23 +00:00
|
|
|
</SafeAreaView>
|
2019-01-30 15:43:57 +00:00
|
|
|
|
2018-03-07 15:23:04 +00:00
|
|
|
<TestConnectionInfo />
|
2019-10-11 13:33:07 +00:00
|
|
|
{ this._renderConferenceNotification() }
|
2020-04-06 15:14:32 +00:00
|
|
|
|
2021-05-07 07:58:57 +00:00
|
|
|
{_shouldDisplayTileView && <Toolbox />}
|
2019-10-11 13:33:07 +00:00
|
|
|
</>
|
2016-10-05 14:36:59 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-04-24 13:24:10 +00:00
|
|
|
/**
|
2019-10-11 13:33:07 +00:00
|
|
|
* Renders the content for the Conference container when in "reduced UI" mode.
|
2018-04-24 13:24:10 +00:00
|
|
|
*
|
|
|
|
* @private
|
2019-10-11 13:33:07 +00:00
|
|
|
* @returns {React$Element}
|
2018-04-24 13:24:10 +00:00
|
|
|
*/
|
2019-10-11 13:33:07 +00:00
|
|
|
_renderContentForReducedUi() {
|
|
|
|
const { _connecting } = this.props;
|
2019-05-28 13:32:29 +00:00
|
|
|
|
2018-08-31 20:09:49 +00:00
|
|
|
return (
|
2019-10-11 13:33:07 +00:00
|
|
|
<>
|
|
|
|
<LargeVideo onClick = { this._onClick } />
|
|
|
|
|
|
|
|
{
|
|
|
|
_connecting
|
|
|
|
&& <TintedView>
|
|
|
|
<LoadingIndicator />
|
|
|
|
</TintedView>
|
|
|
|
}
|
|
|
|
</>
|
|
|
|
);
|
2018-04-24 13:24:10 +00:00
|
|
|
}
|
2019-03-20 20:09:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a container for notifications to be displayed by the
|
|
|
|
* base/notifications feature.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {React$Element}
|
|
|
|
*/
|
2019-10-11 13:33:07 +00:00
|
|
|
_renderNotificationsContainer() {
|
2019-03-20 20:09:23 +00:00
|
|
|
const notificationsStyle = {};
|
|
|
|
|
|
|
|
// In the landscape mode (wide) there's problem with notifications being
|
|
|
|
// shadowed by the filmstrip rendered on the right. This makes the "x"
|
|
|
|
// button not clickable. In order to avoid that a margin of the
|
|
|
|
// filmstrip's size is added to the right.
|
|
|
|
//
|
|
|
|
// Pawel: after many attempts I failed to make notifications adjust to
|
|
|
|
// their contents width because of column and rows being used in the
|
|
|
|
// flex layout. The only option that seemed to limit the notification's
|
|
|
|
// size was explicit 'width' value which is not better than the margin
|
|
|
|
// added here.
|
2020-06-02 09:03:17 +00:00
|
|
|
const { _aspectRatio, _filmstripVisible } = this.props;
|
|
|
|
|
|
|
|
if (_filmstripVisible && _aspectRatio !== ASPECT_RATIO_NARROW) {
|
2019-03-20 20:09:23 +00:00
|
|
|
notificationsStyle.marginRight = FILMSTRIP_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.renderNotificationsContainer(
|
|
|
|
{
|
|
|
|
style: notificationsStyle
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2016-12-12 01:02:50 +00:00
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
_setToolboxVisible: (boolean) => void;
|
2017-09-25 17:26:15 +00:00
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
/**
|
|
|
|
* Dispatches an action changing the visibility of the {@link Toolbox}.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @param {boolean} visible - Pass {@code true} to show the
|
|
|
|
* {@code Toolbox} or {@code false} to hide it.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_setToolboxVisible(visible) {
|
|
|
|
this.props.dispatch(setToolboxVisible(visible));
|
|
|
|
}
|
2017-02-16 23:02:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-12 17:42:38 +00:00
|
|
|
* Maps (parts of) the redux state to the associated {@code Conference}'s props.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
2018-02-12 17:42:38 +00:00
|
|
|
* @param {Object} state - The redux state.
|
2017-02-16 23:02:40 +00:00
|
|
|
* @private
|
2019-02-07 22:52:31 +00:00
|
|
|
* @returns {Props}
|
2017-02-16 23:02:40 +00:00
|
|
|
*/
|
|
|
|
function _mapStateToProps(state) {
|
2019-05-22 10:01:58 +00:00
|
|
|
const { connecting, connection } = state['features/base/connection'];
|
core: refactor routing
Unfortunately, as the Jitsi Meet development evolved the routing mechanism
became more complex and thre logic ended up spread across multiple parts of the
codebase, which made it hard to follow and extend.
This change aims to fix that by rewriting the routing logic and centralizing it
in (pretty much) a single place, with no implicit inter-dependencies.
In order to arrive there, however, some extra changes were needed, which were
not caught early enough and are thus part of this change:
- JitsiMeetJS initialization is now synchronous: there is nothing async about
it, and the only async requirement (Temasys support) was lifted. See [0].
- WebRTC support can be detected early: building on top of the above, WebRTC
support can now be detected immediately, so take advantage of this to simplify
how we handle unsupported browsers. See [0].
The new router takes decissions based on the Redux state at the time of
invocation. A route can be represented by either a component or a URl reference,
with the latter taking precedence. On mobile, obviously, there is no concept of
URL reference so routing is based solely on components.
[0]: https://github.com/jitsi/lib-jitsi-meet/pull/779
2018-06-29 07:58:31 +00:00
|
|
|
const {
|
|
|
|
conference,
|
|
|
|
joining,
|
2020-04-15 13:13:43 +00:00
|
|
|
membersOnly,
|
2019-02-07 22:52:31 +00:00
|
|
|
leaving
|
core: refactor routing
Unfortunately, as the Jitsi Meet development evolved the routing mechanism
became more complex and thre logic ended up spread across multiple parts of the
codebase, which made it hard to follow and extend.
This change aims to fix that by rewriting the routing logic and centralizing it
in (pretty much) a single place, with no implicit inter-dependencies.
In order to arrive there, however, some extra changes were needed, which were
not caught early enough and are thus part of this change:
- JitsiMeetJS initialization is now synchronous: there is nothing async about
it, and the only async requirement (Temasys support) was lifted. See [0].
- WebRTC support can be detected early: building on top of the above, WebRTC
support can now be detected immediately, so take advantage of this to simplify
how we handle unsupported browsers. See [0].
The new router takes decissions based on the Redux state at the time of
invocation. A route can be represented by either a component or a URl reference,
with the latter taking precedence. On mobile, obviously, there is no concept of
URL reference so routing is based solely on components.
[0]: https://github.com/jitsi/lib-jitsi-meet/pull/779
2018-06-29 07:58:31 +00:00
|
|
|
} = state['features/base/conference'];
|
2021-06-11 13:15:44 +00:00
|
|
|
const { isOpen } = state['features/participants-pane'];
|
2020-06-02 09:03:17 +00:00
|
|
|
const { aspectRatio, reducedUI } = state['features/base/responsive-ui'];
|
2022-04-06 12:06:48 +00:00
|
|
|
const participantCount = getParticipantCount(state);
|
2017-09-14 10:18:47 +00:00
|
|
|
|
|
|
|
// XXX There is a window of time between the successful establishment of the
|
|
|
|
// XMPP connection and the subsequent commencement of joining the MUC during
|
|
|
|
// which the app does not appear to be doing anything according to the redux
|
|
|
|
// state. In order to not toggle the _connecting props during the window of
|
|
|
|
// time in question, define _connecting as follows:
|
|
|
|
// - the XMPP connection is connecting, or
|
|
|
|
// - the XMPP connection is connected and the conference is joining, or
|
|
|
|
// - the XMPP connection is connected and we have no conference yet, nor we
|
|
|
|
// are leaving one.
|
|
|
|
const connecting_
|
2020-04-15 13:13:43 +00:00
|
|
|
= connecting || (connection && (!membersOnly && (joining || (!conference && !leaving))));
|
2017-09-14 10:18:47 +00:00
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
return {
|
2019-02-07 22:52:31 +00:00
|
|
|
...abstractMapStateToProps(state),
|
2020-06-02 09:03:17 +00:00
|
|
|
_aspectRatio: aspectRatio,
|
2019-05-28 13:32:29 +00:00
|
|
|
_calendarEnabled: isCalendarEnabled(state),
|
2017-09-14 10:18:47 +00:00
|
|
|
_connecting: Boolean(connecting_),
|
2018-08-29 19:04:05 +00:00
|
|
|
_filmstripVisible: isFilmstripVisible(state),
|
2021-03-08 21:11:39 +00:00
|
|
|
_fullscreenEnabled: getFeatureFlag(state, FULLSCREEN_ENABLED, true),
|
2022-04-06 12:06:48 +00:00
|
|
|
_isOneToOneConference: Boolean(participantCount === 2),
|
2021-06-29 14:05:11 +00:00
|
|
|
_isParticipantsPaneOpen: isOpen,
|
2019-04-11 10:04:50 +00:00
|
|
|
_largeVideoParticipantId: state['features/large-video'].participantId,
|
2019-05-24 11:06:05 +00:00
|
|
|
_pictureInPictureEnabled: getFeatureFlag(state, PIP_ENABLED),
|
2018-02-02 13:41:30 +00:00
|
|
|
_reducedUI: reducedUI,
|
2021-08-20 08:53:11 +00:00
|
|
|
_showLobby: getIsLobbyVisible(state),
|
2019-08-20 13:12:38 +00:00
|
|
|
_toolboxVisible: isToolboxVisible(state)
|
2017-02-16 23:02:40 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-01-13 12:15:53 +00:00
|
|
|
export default withSafeAreaInsets(connect(_mapStateToProps)(Conference));
|