jiti-meet/react/features/calendar-sync/components/ConferenceNotification.nati...

297 lines
8.1 KiB
JavaScript
Raw Normal View History

2018-02-12 15:53:23 +00:00
// @flow
2018-04-16 02:04:57 +00:00
2018-02-12 15:53:23 +00:00
import React, { Component } from 'react';
2018-04-16 02:04:57 +00:00
import { Text, TouchableOpacity, View } from 'react-native';
2018-02-12 15:53:23 +00:00
import { appNavigate } from '../../app';
import { getURLWithoutParamsNormalized } from '../../base/connection';
2018-02-12 15:53:23 +00:00
import { Icon } from '../../base/font-icons';
2018-04-16 02:04:57 +00:00
import { getLocalizedDateFormatter, translate } from '../../base/i18n';
2019-03-21 16:38:29 +00:00
import { connect } from '../../base/redux';
2018-02-12 15:53:23 +00:00
import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
import styles from './styles';
const ALERT_MILLISECONDS = 5 * 60 * 1000;
2018-06-04 19:52:51 +00:00
/**
* The type of the React {@code Component} props of
* {@link ConferenceNotification}.
*/
2018-02-12 15:53:23 +00:00
type Props = {
/**
* The current aspect ratio of the screen.
*/
_aspectRatio: Symbol,
/**
* The URL of the current conference without params.
*/
_currentConferenceURL: string,
/**
* The calendar event list.
*/
_eventList: Array<Object>,
2018-04-16 02:04:57 +00:00
/**
* The Redux dispatch function.
*/
dispatch: Function,
2018-02-12 15:53:23 +00:00
/**
* The translate function.
*/
t: Function
};
2018-06-04 19:52:51 +00:00
/**
* The type of the React {@code Component} state of
* {@link ConferenceNotification}.
*/
2018-02-12 15:53:23 +00:00
type State = {
/**
* The event object to display the notification for.
*/
event?: Object
};
/**
2018-04-16 02:04:57 +00:00
* Component to display a permanent badge-like notification on the conference
* screen when another meeting is about to start.
2018-02-12 15:53:23 +00:00
*/
class ConferenceNotification extends Component<Props, State> {
updateIntervalId: IntervalID;
2018-02-12 15:53:23 +00:00
/**
* Constructor of the ConferenceNotification component.
*
* @inheritdoc
*/
2018-05-22 14:23:03 +00:00
constructor(props: Props) {
2018-02-12 15:53:23 +00:00
super(props);
this.state = {
event: undefined
};
2018-06-04 19:52:51 +00:00
// Bind event handlers so they are only bound once per instance.
2018-02-12 15:53:23 +00:00
this._getNotificationContentStyle
= this._getNotificationContentStyle.bind(this);
this._getNotificationPosition
= this._getNotificationPosition.bind(this);
this._maybeDisplayNotification
= this._maybeDisplayNotification.bind(this);
this._onGoToNext = this._onGoToNext.bind(this);
}
/**
* Implements React Component's componentDidMount.
*
* @inheritdoc
*/
componentDidMount() {
this.updateIntervalId = setInterval(
this._maybeDisplayNotification,
10 * 1000
);
}
/**
* Implements React Component's componentWillUnmount.
*
* @inheritdoc
*/
componentWillUnmount() {
2018-05-22 14:23:03 +00:00
clearInterval(this.updateIntervalId);
2018-02-12 15:53:23 +00:00
}
/**
2018-04-16 02:04:57 +00:00
* Implements the React Components's render.
2018-02-12 15:53:23 +00:00
*
* @inheritdoc
*/
render() {
const { event } = this.state;
const { t } = this.props;
if (event) {
const now = Date.now();
const label
= event.startDate < now && event.endDate > now
? 'calendarSync.ongoingMeeting'
: 'calendarSync.nextMeeting';
2018-02-12 15:53:23 +00:00
return (
<View
style = { [
styles.notificationContainer,
this._getNotificationPosition()
] } >
<View
style = { this._getNotificationContentStyle() }>
<TouchableOpacity
onPress = { this._onGoToNext } >
<View style = { styles.touchableView }>
<View
style = {
styles.notificationTextContainer
}>
<Text style = { styles.notificationText }>
{ t(label) }
2018-02-12 15:53:23 +00:00
</Text>
<Text style = { styles.notificationText }>
{
getLocalizedDateFormatter(
event.startDate
).fromNow()
}
</Text>
</View>
<View
style = {
styles.notificationIconContainer
}>
<Icon
name = 'navigate_next'
style = { styles.notificationIcon } />
</View>
</View>
</TouchableOpacity>
</View>
</View>
);
}
return null;
}
2018-05-22 14:23:03 +00:00
_getNotificationContentStyle: () => Array<Object>;
2018-02-12 15:53:23 +00:00
/**
* Decides the color of the notification and some additional
* styles based on notificationPosition.
*
* @private
* @returns {Array<Object>}
*/
_getNotificationContentStyle() {
const { event } = this.state;
const { _aspectRatio } = this.props;
const now = Date.now();
const style = [
styles.notificationContent
];
if (event && event.startDate < now && event.endDate > now) {
style.push(styles.notificationContentPast);
} else {
style.push(styles.notificationContentNext);
}
if (_aspectRatio === ASPECT_RATIO_NARROW) {
style.push(styles.notificationContentSide);
} else {
style.push(styles.notificationContentTop);
}
return style;
}
_getNotificationPosition: () => Object;
/**
* Decides the position of the notification.
*
* @private
* @returns {Object}
*/
_getNotificationPosition() {
const { _aspectRatio } = this.props;
if (_aspectRatio === ASPECT_RATIO_NARROW) {
return styles.notificationContainerSide;
}
return styles.notificationContainerTop;
}
_maybeDisplayNotification: () => void;
/**
* Periodically checks if there is an event in the calendar for which we
* need to show a notification.
*
* @private
* @returns {void}
*/
_maybeDisplayNotification() {
const { _currentConferenceURL, _eventList } = this.props;
let eventToShow;
if (_eventList && _eventList.length) {
const now = Date.now();
for (const event of _eventList) {
2018-04-16 02:04:57 +00:00
const eventUrl
2018-09-04 07:29:48 +00:00
= event.url
&& getURLWithoutParamsNormalized(new URL(event.url));
2018-09-04 07:29:48 +00:00
if (eventUrl && eventUrl !== _currentConferenceURL) {
2018-02-12 15:53:23 +00:00
if ((!eventToShow
2018-04-16 02:04:57 +00:00
&& event.startDate > now
&& event.startDate < now + ALERT_MILLISECONDS)
|| (event.startDate < now && event.endDate > now)) {
2018-02-12 15:53:23 +00:00
eventToShow = event;
}
}
}
}
this.setState({
event: eventToShow
});
}
_onGoToNext: () => void;
/**
* Opens the meeting URL that the notification shows.
*
2018-04-16 02:04:57 +00:00
* @private
2018-02-12 15:53:23 +00:00
* @returns {void}
*/
_onGoToNext() {
const { event } = this.state;
if (event && event.url) {
this.props.dispatch(appNavigate(event.url));
}
}
}
/**
* Maps redux state to component props.
*
* @param {Object} state - The redux state.
* @returns {{
2018-04-16 02:04:57 +00:00
* _aspectRatio: Symbol,
* _currentConferenceURL: string,
* _eventList: Array
2018-02-12 15:53:23 +00:00
* }}
*/
2018-04-16 16:39:26 +00:00
function _mapStateToProps(state: Object) {
2018-02-12 15:53:23 +00:00
const { locationURL } = state['features/base/connection'];
return {
_aspectRatio: state['features/base/responsive-ui'].aspectRatio,
_currentConferenceURL:
2018-04-16 02:04:57 +00:00
locationURL ? getURLWithoutParamsNormalized(locationURL) : '',
2018-02-12 15:53:23 +00:00
_eventList: state['features/calendar-sync'].events
};
}
export default translate(connect(_mapStateToProps)(ConferenceNotification));