diff --git a/react/features/calendar-sync/components/ConferenceNotification.native.js b/react/features/calendar-sync/components/ConferenceNotification.native.js index a37f5993c..b7fee65b7 100644 --- a/react/features/calendar-sync/components/ConferenceNotification.native.js +++ b/react/features/calendar-sync/components/ConferenceNotification.native.js @@ -267,7 +267,7 @@ class ConferenceNotification extends Component { * _eventList: Array * }} */ -export function _mapStateToProps(state: Object) { +function _mapStateToProps(state: Object) { const { locationURL } = state['features/base/connection']; return { diff --git a/react/features/calendar-sync/components/MeetingList.native.js b/react/features/calendar-sync/components/MeetingList.native.js index dfa5fcbf7..516600b65 100644 --- a/react/features/calendar-sync/components/MeetingList.native.js +++ b/react/features/calendar-sync/components/MeetingList.native.js @@ -10,6 +10,7 @@ import { NavigateSectionList } from '../../base/react'; import { openSettings } from '../../mobile/permissions'; import { refreshCalendar } from '../actions'; +import { CALENDAR_ENABLED } from '../constants'; import styles from './styles'; type Props = { @@ -59,6 +60,23 @@ class MeetingList extends Component { _eventList: [] }; + /** + * Public API method for {@code Component}s rendered in + * {@link AbstractPagedList}. When invoked, refreshes the calendar entries + * in the app. + * + * Note: It is a static method as the {@code Component} may not be + * initialized yet when the UI invokes refresh (e.g. {@link TabBarIOS} tab + * change). + * + * @param {Function} dispatch - The Redux dispatch function. + * @public + * @returns {void} + */ + static refresh(dispatch) { + dispatch(refreshCalendar()); + } + /** * Constructor of the MeetingList component. * @@ -82,21 +100,6 @@ class MeetingList extends Component { this._toDateString = this._toDateString.bind(this); } - /** - * Implements React Component's componentWillReceiveProps. - * - * @inheritdoc - */ - componentWillReceiveProps(newProps) { - const { displayed } = this.props; - - if (newProps.displayed && !displayed) { - const { dispatch } = this.props; - - dispatch(refreshCalendar()); - } - } - /** * Implements the React Components's render. * @@ -266,7 +269,7 @@ class MeetingList extends Component { * _eventList: Array * }} */ -export function _mapStateToProps(state: Object) { +function _mapStateToProps(state: Object) { const calendarSyncState = state['features/calendar-sync']; return { @@ -275,4 +278,6 @@ export function _mapStateToProps(state: Object) { }; } -export default translate(connect(_mapStateToProps)(MeetingList)); +export default CALENDAR_ENABLED + ? translate(connect(_mapStateToProps)(MeetingList)) + : undefined; diff --git a/react/features/calendar-sync/constants.js b/react/features/calendar-sync/constants.js new file mode 100644 index 000000000..657e36869 --- /dev/null +++ b/react/features/calendar-sync/constants.js @@ -0,0 +1,26 @@ +// @flow + +import { NativeModules } from 'react-native'; + +/** + * The indicator which determines whether the calendar feature is enabled by the + * app. + * + * @type {boolean} + */ +export const CALENDAR_ENABLED = _isCalendarEnabled(); + +/** + * Determines whether the calendar feature is enabled by the app. For + * example, Apple through its App Store requires + * {@code NSCalendarsUsageDescription} in the app's Info.plist or App Store + * rejects the app. + * + * @returns {boolean} If the app has enabled the calendar feature, {@code true}; + * otherwise, {@code false}. + */ +function _isCalendarEnabled() { + const { calendarEnabled } = NativeModules.AppInfo; + + return typeof calendarEnabled === 'undefined' ? true : calendarEnabled; +} diff --git a/react/features/calendar-sync/index.js b/react/features/calendar-sync/index.js index 7f0ef0251..daaa5d02a 100644 --- a/react/features/calendar-sync/index.js +++ b/react/features/calendar-sync/index.js @@ -1,4 +1,3 @@ -export * from './actions'; export * from './components'; import './middleware'; diff --git a/react/features/calendar-sync/middleware.js b/react/features/calendar-sync/middleware.js index 7fb23ee18..7ac8a6a62 100644 --- a/react/features/calendar-sync/middleware.js +++ b/react/features/calendar-sync/middleware.js @@ -1,6 +1,5 @@ // @flow -import { NativeModules } from 'react-native'; import RNCalendarEvents from 'react-native-calendar-events'; import { APP_WILL_MOUNT } from '../app'; @@ -15,6 +14,7 @@ import { setCalendarEvents } from './actions'; import { REFRESH_CALENDAR } from './actionTypes'; +import { CALENDAR_ENABLED } from './constants'; const logger = require('jitsi-meet-logger').getLogger(__filename); @@ -22,30 +22,31 @@ const FETCH_END_DAYS = 10; const FETCH_START_DAYS = -1; const MAX_LIST_LENGTH = 10; -MiddlewareRegistry.register(store => next => action => { - const result = next(action); +CALENDAR_ENABLED + && MiddlewareRegistry.register(store => next => action => { + const result = next(action); - switch (action.type) { - case APP_STATE_CHANGED: - _maybeClearAccessStatus(store, action); - break; + switch (action.type) { + case APP_STATE_CHANGED: + _maybeClearAccessStatus(store, action); + break; - case APP_WILL_MOUNT: - _ensureDefaultServer(store); - _fetchCalendarEntries(store, false, false); - break; + case APP_WILL_MOUNT: + _ensureDefaultServer(store); + _fetchCalendarEntries(store, false, false); + break; - case REFRESH_CALENDAR: - _fetchCalendarEntries(store, true, action.forcePermission); - break; + case REFRESH_CALENDAR: + _fetchCalendarEntries(store, true, action.forcePermission); + break; - case SET_ROOM: - _parseAndAddKnownDomain(store); - break; - } + case SET_ROOM: + _parseAndAddKnownDomain(store); + break; + } - return result; -}); + return result; + }); /** * Clears the calendar access status when the app comes back from the @@ -123,11 +124,6 @@ function _fetchCalendarEntries( { dispatch, getState }, maybePromptForPermission, forcePermission) { - if (!_isCalendarEnabled()) { - // The calendar feature is not enabled. - return; - } - const state = getState()['features/calendar-sync']; const promptForPermission = (maybePromptForPermission && !state.authorization) @@ -203,20 +199,6 @@ function _getURLFromEvent(event, knownDomains) { return null; } -/** - * Determines whether the calendar feature is enabled by the app. For - * example, Apple through its App Store requires NSCalendarsUsageDescription in - * the app's Info.plist or App Store rejects the app. - * - * @returns {boolean} If the app has enabled the calendar feature, {@code true}; - * otherwise, {@code false}. - */ -export function _isCalendarEnabled() { - const { calendarEnabled } = NativeModules.AppInfo; - - return typeof calendarEnabled === 'undefined' ? true : calendarEnabled; -} - /** * Retrieves the domain name of a room upon join and stores it in the known * domain list, if not present yet. diff --git a/react/features/calendar-sync/reducer.js b/react/features/calendar-sync/reducer.js index fc646ac11..d76fb93ca 100644 --- a/react/features/calendar-sync/reducer.js +++ b/react/features/calendar-sync/reducer.js @@ -8,6 +8,7 @@ import { SET_CALENDAR_AUTHORIZATION, SET_CALENDAR_EVENTS } from './actionTypes'; +import { CALENDAR_ENABLED } from './constants'; const DEFAULT_STATE = { /** @@ -24,31 +25,33 @@ const MAX_DOMAIN_LIST_SIZE = 10; const STORE_NAME = 'features/calendar-sync'; -PersistenceRegistry.register(STORE_NAME, { - knownDomains: true -}); +CALENDAR_ENABLED + && PersistenceRegistry.register(STORE_NAME, { + knownDomains: true + }); -ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => { - switch (action.type) { - case ADD_KNOWN_DOMAIN: - return _addKnownDomain(state, action); +CALENDAR_ENABLED + && ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => { + switch (action.type) { + case ADD_KNOWN_DOMAIN: + return _addKnownDomain(state, action); - case SET_CALENDAR_AUTHORIZATION: - return { - ...state, - authorization: action.status - }; + case SET_CALENDAR_AUTHORIZATION: + return { + ...state, + authorization: action.status + }; - case SET_CALENDAR_EVENTS: - return { - ...state, - events: action.events - }; + case SET_CALENDAR_EVENTS: + return { + ...state, + events: action.events + }; - default: - return state; - } -}); + default: + return state; + } + }); /** * Adds a new domain to the known domain list if not present yet. diff --git a/react/features/welcome/components/AbstractPagedList.js b/react/features/welcome/components/AbstractPagedList.js deleted file mode 100644 index 0ea76ce49..000000000 --- a/react/features/welcome/components/AbstractPagedList.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow - -import { Component } from 'react'; - -/** - * The page to be displayed on render. - */ -export const DEFAULT_PAGE = 0; - -type Props = { - - /** - * Indicates if the list is disabled or not. - */ - disabled: boolean, - - /** - * The Redux dispatch function. - */ - dispatch: Function, - - /** - * The i18n translate function - */ - t: Function -} - -type State = { - - /** - * The currently selected page. - */ - pageIndex: number -} - -/** - * Abstract class for the platform specific paged lists. - */ -export default class AbstractPagedList extends Component { - /** - * Constructor of the component. - * - * @inheritdoc - */ - constructor(props: Props) { - super(props); - - this.state = { - pageIndex: DEFAULT_PAGE - }; - } - -} diff --git a/react/features/welcome/components/AbstractPagedList.native.js b/react/features/welcome/components/AbstractPagedList.native.js new file mode 100644 index 000000000..d07b9ee08 --- /dev/null +++ b/react/features/welcome/components/AbstractPagedList.native.js @@ -0,0 +1,91 @@ +// @flow + +import React, { Component } from 'react'; +import { View } from 'react-native'; +import { isCalendarEnabled } from '../../calendar-sync'; +import { RecentList } from '../../recent-list'; + +import styles from './styles'; + +/** + * The page to be displayed on render. + */ +export const DEFAULT_PAGE = 0; + +type Props = { + + /** + * Indicates if the list is disabled or not. + */ + disabled: boolean, + + /** + * The Redux dispatch function. + */ + dispatch: Function, + + /** + * The i18n translate function + */ + t: Function +} + +type State = { + + /** + * The currently selected page. + */ + pageIndex: number +} + +/** + * Abstract class for the platform specific paged lists. + */ +export default class AbstractPagedList extends Component { + /** + * True if the calendar feature is enabled on the platform, false otherwise. + */ + _calendarEnabled: boolean + + /** + * Constructor of the component. + * + * @inheritdoc + */ + constructor(props: Props) { + super(props); + + this._calendarEnabled = isCalendarEnabled(); + + this.state = { + pageIndex: DEFAULT_PAGE + }; + } + + /** + * Renders the component. + * + * @inheritdoc + */ + render() { + const { disabled } = this.props; + + return ( + + { + (this._calendarEnabled && this._renderPagedList(disabled)) + || + } + + ); + } + + _renderPagedList: boolean => Object + +} diff --git a/react/features/welcome/components/AbstractPagedList.web.js b/react/features/welcome/components/AbstractPagedList.web.js new file mode 100644 index 000000000..e69de29bb diff --git a/react/features/welcome/components/PagedList.android.js b/react/features/welcome/components/PagedList.android.js index a40cef823..4a1ee28b5 100644 --- a/react/features/welcome/components/PagedList.android.js +++ b/react/features/welcome/components/PagedList.android.js @@ -35,20 +35,17 @@ export default class PagedList extends AbstractPagedList { } /** - * Renders the paged list. + * Renders the entire paged list if calendar is enabled. * - * @inheritdoc + * @param {boolean} disabled - True if the rendered lists should be + * disabled. + * @returns {ReactElement} */ - render() { - const { disabled } = this.props; + _renderPagedList(disabled) { const { pageIndex } = this.state; return ( - + - - - - - - - - - + + + + + + + + ); }