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

300 lines
8.2 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 { connect } from 'react-redux';
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';
2018-02-12 15:53:23 +00:00
import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
Google & Microsoft calendar API integration (#3340) * Refactor calendar-sync feature to be loaded on web. For the web part it just adds new property to enable/disable calendar web integration, disabled by default. * Initial implementation of retrieving google calendar events. * Initial implementation of retrieving microsoft calendar events. * Fixes comments. * Rework to use the promise part of microsoft-graph-client api. * Moves dispatching some actions, fixing comments. * Makes sure we do not initializeClient google-api client multiple times. * Do not try to login when fetching calendar entries. The case where there is a calendar type google selected, but not logged in, trying to login on loading welcome page will show a warning that it tried to open a popup, which was denied by browser. * Updates profile display data on sign in. * Propagate google-api state to calendar-sync only if we use google cal. * Adds sign out action. * Clears the event listener when the popup closes. * Clears calendarIntegrationInstance on signOut. * WIP: UI for calendar settings, refactor auth flows * Clean up some unused constants, functions and exports. * break circular dependency of function and constant * Exports only isCalendarEnabled from functions. * Checks isSignedIn when doing fetchCalendarEntries on web. * address comments List microsoftApiApplicationClientID in undocument config. remove unused SET_CALENDAR_TYPE action use helper for calendar enabled in bootstrap reorder actions reorder imports change order of signin -> set type -> update profile add logging for signout error reword setting dialog desc to avoid redundancy add jsdoc to microsoft button props reorder calendar constants move default state to reducer (not reused anywhere) update comment about calendar-sync due to removal of getCalendarState update comment for getCalendarIntegration remove vague comment alpha order reducer, return default state on reset alpha order persistence registry remove unnecessary getType from apis update comments in microsoftCalendar alpha order google-api exports, use api.get in loadGoogleAPI set jsdoc for google signin props alpha order googleapi methods fix calendartab docs * Moves fetching calendar from APP_WILL_MOUNT to SET_CONFIG. The web part needs configuration in order to refresh tokens (Microsoft). * Fixes storing token expire time and refreshing tokens in Microsoft impl. * Address comments updateProfile changed to getCurrentEmail rename result to results stop storing integration in redux, store if ready for use use existing helpers to parse redirect url * update jsdocs, get google app id from redux * clear integration instead of actual sign out
2018-08-15 20:11:54 +00:00
import { isCalendarEnabled } from '../functions';
2018-02-12 15:53:23 +00:00
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
};
}
Google & Microsoft calendar API integration (#3340) * Refactor calendar-sync feature to be loaded on web. For the web part it just adds new property to enable/disable calendar web integration, disabled by default. * Initial implementation of retrieving google calendar events. * Initial implementation of retrieving microsoft calendar events. * Fixes comments. * Rework to use the promise part of microsoft-graph-client api. * Moves dispatching some actions, fixing comments. * Makes sure we do not initializeClient google-api client multiple times. * Do not try to login when fetching calendar entries. The case where there is a calendar type google selected, but not logged in, trying to login on loading welcome page will show a warning that it tried to open a popup, which was denied by browser. * Updates profile display data on sign in. * Propagate google-api state to calendar-sync only if we use google cal. * Adds sign out action. * Clears the event listener when the popup closes. * Clears calendarIntegrationInstance on signOut. * WIP: UI for calendar settings, refactor auth flows * Clean up some unused constants, functions and exports. * break circular dependency of function and constant * Exports only isCalendarEnabled from functions. * Checks isSignedIn when doing fetchCalendarEntries on web. * address comments List microsoftApiApplicationClientID in undocument config. remove unused SET_CALENDAR_TYPE action use helper for calendar enabled in bootstrap reorder actions reorder imports change order of signin -> set type -> update profile add logging for signout error reword setting dialog desc to avoid redundancy add jsdoc to microsoft button props reorder calendar constants move default state to reducer (not reused anywhere) update comment about calendar-sync due to removal of getCalendarState update comment for getCalendarIntegration remove vague comment alpha order reducer, return default state on reset alpha order persistence registry remove unnecessary getType from apis update comments in microsoftCalendar alpha order google-api exports, use api.get in loadGoogleAPI set jsdoc for google signin props alpha order googleapi methods fix calendartab docs * Moves fetching calendar from APP_WILL_MOUNT to SET_CONFIG. The web part needs configuration in order to refresh tokens (Microsoft). * Fixes storing token expire time and refreshing tokens in Microsoft impl. * Address comments updateProfile changed to getCurrentEmail rename result to results stop storing integration in redux, store if ready for use use existing helpers to parse redirect url * update jsdocs, get google app id from redux * clear integration instead of actual sign out
2018-08-15 20:11:54 +00:00
export default isCalendarEnabled()
? translate(connect(_mapStateToProps)(ConferenceNotification))
: undefined;