2017-11-17 19:06:47 +00:00
|
|
|
// @flow
|
|
|
|
|
2019-03-20 20:09:23 +00:00
|
|
|
import React from 'react';
|
2019-07-11 11:32:17 +00:00
|
|
|
import { NativeModules, SafeAreaView, StatusBar, View } from 'react-native';
|
2019-07-12 08:06:49 +00:00
|
|
|
import LinearGradient from 'react-native-linear-gradient';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-01-30 13:05:35 +00:00
|
|
|
import { appNavigate } from '../../../app';
|
2019-05-24 11:06:05 +00:00
|
|
|
import { PIP_ENABLED, getFeatureFlag } from '../../../base/flags';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { getParticipantCount } from '../../../base/participants';
|
|
|
|
import { Container, LoadingIndicator, TintedView } from '../../../base/react';
|
2019-05-23 11:29:40 +00:00
|
|
|
import { connect } from '../../../base/redux';
|
2018-08-29 19:04:05 +00:00
|
|
|
import {
|
2019-03-20 20:09:23 +00:00
|
|
|
isNarrowAspectRatio,
|
2018-08-29 19:04:05 +00:00
|
|
|
makeAspectRatioAware
|
2019-01-30 13:05:35 +00:00
|
|
|
} from '../../../base/responsive-ui';
|
|
|
|
import { TestConnectionInfo } from '../../../base/testing';
|
2019-05-28 13:32:29 +00:00
|
|
|
import { ConferenceNotification, isCalendarEnabled } from '../../../calendar-sync';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { Chat } from '../../../chat';
|
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';
|
|
|
|
import { LargeVideo } from '../../../large-video';
|
2019-07-11 11:32:17 +00:00
|
|
|
import { BackButtonRegistry } from '../../../mobile/back-button';
|
2019-02-26 10:41:57 +00:00
|
|
|
import { AddPeopleDialog, CalleeInfoContainer } from '../../../invite';
|
2019-01-30 13:05:35 +00:00
|
|
|
import { Captions } from '../../../subtitles';
|
|
|
|
import { setToolboxVisible, Toolbox } from '../../../toolbox';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-03-20 20:09:23 +00:00
|
|
|
import {
|
|
|
|
AbstractConference,
|
|
|
|
abstractMapStateToProps
|
|
|
|
} from '../AbstractConference';
|
2019-02-05 10:10:15 +00:00
|
|
|
import Labels from './Labels';
|
2019-01-30 15:43:57 +00:00
|
|
|
import NavigationBar from './NavigationBar';
|
2019-07-12 08:06:49 +00:00
|
|
|
import styles, { NAVBAR_GRADIENT_COLORS } from './styles';
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-02-07 22:52:31 +00:00
|
|
|
import type { AbstractProps } from '../AbstractConference';
|
|
|
|
|
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
|
|
|
|
2019-05-28 13:32:29 +00:00
|
|
|
/**
|
|
|
|
* Wherther the calendar feature is enabled or not.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_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
|
|
|
* @private
|
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.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_filmstripVisible: boolean,
|
|
|
|
|
2019-04-11 10:04:50 +00:00
|
|
|
/**
|
|
|
|
* The ID of the participant currently on stage (if any)
|
|
|
|
*/
|
|
|
|
_largeVideoParticipantId: string,
|
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
2019-05-23 11:29:40 +00:00
|
|
|
* The number of participants in the conference.
|
2017-11-13 15:54:04 +00:00
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
2019-05-23 11:29:40 +00:00
|
|
|
_participantCount: number,
|
2017-09-25 17:26:15 +00:00
|
|
|
|
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
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
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
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_reducedUI: boolean,
|
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
2018-08-31 20:06:48 +00:00
|
|
|
* The handler which dispatches the (redux) action {@link setToolboxVisible}
|
|
|
|
* to show/hide the {@link Toolbox}.
|
2017-11-13 15:54:04 +00:00
|
|
|
*
|
2018-08-31 20:06:48 +00:00
|
|
|
* @param {boolean} visible - {@code true} to show the {@code Toolbox} or
|
|
|
|
* {@code false} to hide it.
|
2017-11-13 15:54:04 +00:00
|
|
|
* @private
|
2018-08-31 20:06:48 +00:00
|
|
|
* @returns {void}
|
2017-11-13 15:54:04 +00:00
|
|
|
*/
|
|
|
|
_setToolboxVisible: Function,
|
2017-02-16 23:02:40 +00:00
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines whether the Toolbox is visible.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
2018-04-16 15:06:11 +00:00
|
|
|
_toolboxVisible: boolean,
|
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
/**
|
|
|
|
* The redux {@code dispatch} function.
|
|
|
|
*/
|
|
|
|
dispatch: Function
|
2017-11-13 15:54:04 +00:00
|
|
|
};
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2017-11-13 15:54:04 +00:00
|
|
|
/**
|
|
|
|
* The conference page of the mobile (i.e. React Native) application.
|
|
|
|
*/
|
2019-03-20 20:09:23 +00:00
|
|
|
class Conference extends AbstractConference<Props, *> {
|
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);
|
|
|
|
|
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);
|
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() {
|
2019-07-11 11:32:17 +00:00
|
|
|
BackButtonRegistry.addListener(this._onHardwareBackPress);
|
2017-09-25 17:26:15 +00:00
|
|
|
|
2018-05-18 19:35:58 +00:00
|
|
|
// Show the toolbox if we are the only participant; otherwise, the whole
|
|
|
|
// UI looks too unpopulated the LargeVideo visible.
|
2019-05-23 11:29:40 +00:00
|
|
|
this.props._participantCount === 1 && this._setToolboxVisible(true);
|
2017-01-03 21:06:47 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2018-12-07 02:15:03 +00:00
|
|
|
* Implements React's {@link Component#componentDidUpdate()}.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
2019-05-22 10:01:58 +00:00
|
|
|
componentDidUpdate(prevProps: Props) {
|
2018-05-18 13:19:25 +00:00
|
|
|
const {
|
2019-05-22 10:01:58 +00:00
|
|
|
_participantCount: oldParticipantCount
|
|
|
|
} = prevProps;
|
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 {
|
|
|
|
_participantCount: newParticipantCount,
|
2018-12-07 02:15:03 +00:00
|
|
|
_toolboxVisible
|
|
|
|
} = this.props;
|
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
|
|
|
|
2018-12-07 02:15:03 +00:00
|
|
|
if (oldParticipantCount === 1
|
|
|
|
&& newParticipantCount > 1
|
|
|
|
&& _toolboxVisible) {
|
2019-05-23 11:29:40 +00:00
|
|
|
this._setToolboxVisible(false);
|
2018-12-07 02:15:03 +00:00
|
|
|
} else if (oldParticipantCount > 1
|
|
|
|
&& newParticipantCount === 1
|
|
|
|
&& !_toolboxVisible) {
|
2019-05-23 11:29:40 +00:00
|
|
|
this._setToolboxVisible(true);
|
2018-05-17 13:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
2019-07-11 11:32:17 +00:00
|
|
|
BackButtonRegistry.removeListener(this._onHardwareBackPress);
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render() {
|
2018-09-13 15:20:22 +00:00
|
|
|
const {
|
|
|
|
_connecting,
|
2019-07-12 08:06:49 +00:00
|
|
|
_filmstripVisible,
|
2019-04-11 10:04:50 +00:00
|
|
|
_largeVideoParticipantId,
|
2018-09-13 15:20:22 +00:00
|
|
|
_reducedUI,
|
2019-07-12 08:06:49 +00:00
|
|
|
_shouldDisplayTileView,
|
|
|
|
_toolboxVisible
|
2018-09-13 15:20:22 +00:00
|
|
|
} = this.props;
|
2019-07-12 08:06:49 +00:00
|
|
|
const showGradient = _toolboxVisible;
|
|
|
|
const applyGradientStretching = _filmstripVisible && isNarrowAspectRatio(this) && !_shouldDisplayTileView;
|
2018-09-13 15:20:22 +00:00
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
return (
|
2018-04-18 18:37:33 +00:00
|
|
|
<Container style = { styles.conference }>
|
2018-02-02 14:50:16 +00:00
|
|
|
<StatusBar
|
2018-04-19 08:50:56 +00:00
|
|
|
barStyle = 'light-content'
|
2018-02-02 14:50:16 +00:00
|
|
|
hidden = { true }
|
|
|
|
translucent = { true } />
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-01-13 19:34:38 +00:00
|
|
|
<Chat />
|
2019-02-26 10:41:57 +00:00
|
|
|
<AddPeopleDialog />
|
2019-01-13 19:34:38 +00:00
|
|
|
|
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
|
|
|
*/
|
2018-09-13 15:20:22 +00:00
|
|
|
_reducedUI || <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
|
|
|
}
|
|
|
|
|
2018-04-05 19:46:31 +00:00
|
|
|
<View
|
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = { styles.toolboxAndFilmstripContainer }>
|
2018-08-23 19:57:12 +00:00
|
|
|
|
2019-07-12 08:06:49 +00:00
|
|
|
{ showGradient && <LinearGradient
|
|
|
|
colors = { NAVBAR_GRADIENT_COLORS }
|
|
|
|
end = {{
|
|
|
|
x: 0.0,
|
|
|
|
y: 0.0
|
|
|
|
}}
|
|
|
|
pointerEvents = 'none'
|
|
|
|
start = {{
|
|
|
|
x: 0.0,
|
2019-07-12 13:03:14 +00:00
|
|
|
y: 1.0
|
2019-07-12 08:06:49 +00:00
|
|
|
}}
|
|
|
|
style = { [
|
|
|
|
styles.bottomGradient,
|
|
|
|
applyGradientStretching ? styles.gradientStretchBottom : undefined
|
|
|
|
] } />}
|
|
|
|
|
2019-02-05 10:10:15 +00:00
|
|
|
<Labels />
|
|
|
|
|
2018-08-23 19:57:12 +00:00
|
|
|
<Captions onPress = { this._onClick } />
|
|
|
|
|
2019-04-11 10:04:50 +00:00
|
|
|
{ _shouldDisplayTileView || <DisplayNameLabel participantId = { _largeVideoParticipantId } /> }
|
2019-01-28 14:55:37 +00:00
|
|
|
|
2017-10-13 16:13:46 +00:00
|
|
|
{/*
|
2019-07-12 08:06:49 +00:00
|
|
|
* The Toolbox is in a stacking layer below the Filmstrip.
|
2017-10-13 16:13:46 +00:00
|
|
|
*/}
|
|
|
|
<Toolbox />
|
2018-08-23 19:57:12 +00:00
|
|
|
|
2017-10-13 16:13:46 +00:00
|
|
|
{/*
|
2017-11-07 14:28:08 +00:00
|
|
|
* The Filmstrip is in a stacking layer above the
|
|
|
|
* LargeVideo. The LargeVideo and the Filmstrip form what
|
|
|
|
* the Web/React app calls "videospace". Presumably, the
|
|
|
|
* name and grouping stem from the fact that these two
|
|
|
|
* React Components depict the videos of the conference's
|
2017-10-13 16:13:46 +00:00
|
|
|
* participants.
|
2018-09-13 15:20:22 +00:00
|
|
|
*/
|
|
|
|
_shouldDisplayTileView ? undefined : <Filmstrip />
|
|
|
|
}
|
2017-10-13 16:13:46 +00:00
|
|
|
</View>
|
2018-08-31 20:06:48 +00:00
|
|
|
|
2019-03-20 20:09:23 +00:00
|
|
|
<SafeAreaView
|
|
|
|
pointerEvents = 'box-none'
|
|
|
|
style = { styles.navBarSafeView }>
|
|
|
|
<NavigationBar />
|
|
|
|
{ this.renderNotificationsContainer() }
|
|
|
|
</SafeAreaView>
|
2019-01-30 15:43:57 +00:00
|
|
|
|
2018-03-07 15:23:04 +00:00
|
|
|
<TestConnectionInfo />
|
2017-05-24 17:01:46 +00:00
|
|
|
|
2018-04-24 13:24:10 +00:00
|
|
|
{
|
|
|
|
this._renderConferenceNotification()
|
|
|
|
}
|
2018-09-18 10:52:52 +00:00
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-11-17 19:06:47 +00:00
|
|
|
_onClick: () => void;
|
|
|
|
|
2016-10-05 14:36:59 +00:00
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* Changes the value of the toolboxVisible state, thus allowing us to switch
|
2017-04-10 17:59:44 +00:00
|
|
|
* between Toolbox and Filmstrip and change their visibility.
|
2016-10-05 14:36:59 +00:00
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
_onClick() {
|
2019-05-23 11:29:40 +00:00
|
|
|
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));
|
|
|
|
});
|
2016-10-05 14:36:59 +00:00
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
return true;
|
2016-10-05 14:36:59 +00:00
|
|
|
}
|
2016-12-12 01:02:50 +00:00
|
|
|
|
2018-04-24 13:24:10 +00:00
|
|
|
/**
|
|
|
|
* Renders the conference notification badge if the feature is enabled.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @returns {React$Node}
|
|
|
|
*/
|
|
|
|
_renderConferenceNotification() {
|
2019-05-28 13:32:29 +00:00
|
|
|
const { _calendarEnabled, _reducedUI } = this.props;
|
|
|
|
|
2018-08-31 20:09:49 +00:00
|
|
|
return (
|
2019-05-28 13:32:29 +00:00
|
|
|
_calendarEnabled && !_reducedUI
|
2018-08-31 20:09:49 +00:00
|
|
|
? <ConferenceNotification />
|
|
|
|
: undefined);
|
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}
|
|
|
|
*/
|
|
|
|
renderNotificationsContainer() {
|
|
|
|
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.
|
|
|
|
if (this.props._filmstripVisible && !isNarrowAspectRatio(this)) {
|
|
|
|
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,
|
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'];
|
2018-02-02 13:41:30 +00:00
|
|
|
const { reducedUI } = state['features/base/responsive-ui'];
|
2019-06-19 12:44:39 +00:00
|
|
|
const { visible } = state['features/toolbox'];
|
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_
|
|
|
|
= connecting || (connection && (joining || (!conference && !leaving)));
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
return {
|
2019-02-07 22:52:31 +00:00
|
|
|
...abstractMapStateToProps(state),
|
|
|
|
|
2019-05-28 13:32:29 +00:00
|
|
|
/**
|
|
|
|
* Wherther the calendar feature is enabled or not.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_calendarEnabled: isCalendarEnabled(state),
|
|
|
|
|
2017-09-14 10:18:47 +00:00
|
|
|
/**
|
|
|
|
* The indicator which determines that we are still connecting to the
|
|
|
|
* conference which includes establishing the XMPP connection and then
|
|
|
|
* joining the room. If truthy, then an activity/loading indicator will
|
|
|
|
* be rendered.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_connecting: Boolean(connecting_),
|
|
|
|
|
2018-08-29 19:04:05 +00:00
|
|
|
/**
|
|
|
|
* Is {@code true} when the filmstrip is currently visible.
|
|
|
|
*/
|
|
|
|
_filmstripVisible: isFilmstripVisible(state),
|
|
|
|
|
2019-04-11 10:04:50 +00:00
|
|
|
/**
|
|
|
|
* The ID of the participant currently on stage.
|
|
|
|
*/
|
|
|
|
_largeVideoParticipantId: state['features/large-video'].participantId,
|
|
|
|
|
2018-05-17 13:23:11 +00:00
|
|
|
/**
|
2018-05-18 13:19:25 +00:00
|
|
|
* The number of participants in the conference.
|
2018-05-17 13:23:11 +00:00
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {number}
|
|
|
|
*/
|
2018-05-22 22:41:53 +00:00
|
|
|
_participantCount: getParticipantCount(state),
|
2018-05-17 13:23:11 +00:00
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
/**
|
|
|
|
* Whether Picture-in-Picture is enabled.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
2019-05-24 11:06:05 +00:00
|
|
|
_pictureInPictureEnabled: getFeatureFlag(state, PIP_ENABLED),
|
2019-05-23 11:29:40 +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
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
_reducedUI: reducedUI,
|
|
|
|
|
2017-02-16 23:02:40 +00:00
|
|
|
/**
|
2017-04-01 05:52:40 +00:00
|
|
|
* The indicator which determines whether the Toolbox is visible.
|
2017-02-16 23:02:40 +00:00
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
2019-06-19 12:44:39 +00:00
|
|
|
_toolboxVisible: visible
|
2017-02-16 23:02:40 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-05-23 11:29:40 +00:00
|
|
|
export default connect(_mapStateToProps)(makeAspectRatioAware(Conference));
|