| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 | 
							- // @flow
 - 
 - import React, { Component } from 'react';
 - import { Text, TouchableOpacity, View } from 'react-native';
 - import { connect } from 'react-redux';
 - 
 - import { appNavigate } from '../../app';
 - import { getURLWithoutParamsNormalized } from '../../base/connection';
 - import { Icon } from '../../base/font-icons';
 - import { getLocalizedDateFormatter, translate } from '../../base/i18n';
 - import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
 - 
 - import { CALENDAR_ENABLED } from '../constants';
 - import styles from './styles';
 - 
 - const ALERT_MILLISECONDS = 5 * 60 * 1000;
 - 
 - /**
 -  * The type of the React {@code Component} props of
 -  * {@link ConferenceNotification}.
 -  */
 - 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>,
 - 
 -     /**
 -      * The Redux dispatch function.
 -      */
 -     dispatch: Function,
 - 
 -     /**
 -      * The translate function.
 -      */
 -     t: Function
 - };
 - 
 - /**
 -  * The type of the React {@code Component} state of
 -  * {@link ConferenceNotification}.
 -  */
 - type State = {
 - 
 -     /**
 -      * The event object to display the notification for.
 -      */
 -     event?: Object
 - };
 - 
 - /**
 -  * Component to display a permanent badge-like notification on the conference
 -  * screen when another meeting is about to start.
 -  */
 - class ConferenceNotification extends Component<Props, State> {
 -     updateIntervalId: IntervalID;
 - 
 -     /**
 -      * Constructor of the ConferenceNotification component.
 -      *
 -      * @inheritdoc
 -      */
 -     constructor(props: Props) {
 -         super(props);
 - 
 -         this.state = {
 -             event: undefined
 -         };
 - 
 -         // Bind event handlers so they are only bound once per instance.
 -         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() {
 -         clearInterval(this.updateIntervalId);
 -     }
 - 
 -     /**
 -      * Implements the React Components's render.
 -      *
 -      * @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';
 - 
 -             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) }
 -                                     </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;
 -     }
 - 
 -     _getNotificationContentStyle: () => Array<Object>;
 - 
 -     /**
 -      * 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) {
 -                 const eventUrl
 -                     = getURLWithoutParamsNormalized(new URL(event.url));
 - 
 -                 if (eventUrl !== _currentConferenceURL) {
 -                     if ((!eventToShow
 -                                 && event.startDate > now
 -                                 && event.startDate < now + ALERT_MILLISECONDS)
 -                             || (event.startDate < now && event.endDate > now)) {
 -                         eventToShow = event;
 -                     }
 -                 }
 -             }
 -         }
 - 
 -         this.setState({
 -             event: eventToShow
 -         });
 -     }
 - 
 -     _onGoToNext: () => void;
 - 
 -     /**
 -      * Opens the meeting URL that the notification shows.
 -      *
 -      * @private
 -      * @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 {{
 -  *     _aspectRatio: Symbol,
 -  *     _currentConferenceURL: string,
 -  *     _eventList: Array
 -  * }}
 -  */
 - function _mapStateToProps(state: Object) {
 -     const { locationURL } = state['features/base/connection'];
 - 
 -     return {
 -         _aspectRatio: state['features/base/responsive-ui'].aspectRatio,
 -         _currentConferenceURL:
 -             locationURL ? getURLWithoutParamsNormalized(locationURL) : '',
 -         _eventList: state['features/calendar-sync'].events
 -     };
 - }
 - 
 - export default CALENDAR_ENABLED
 -     ? translate(connect(_mapStateToProps)(ConferenceNotification))
 -     : undefined;
 
 
  |