Properly gate calendar feature on-off
This commit is contained in:
parent
09482f053b
commit
374e3ccf2c
|
@ -267,7 +267,7 @@ class ConferenceNotification extends Component<Props, State> {
|
|||
* _eventList: Array
|
||||
* }}
|
||||
*/
|
||||
export function _mapStateToProps(state: Object) {
|
||||
function _mapStateToProps(state: Object) {
|
||||
const { locationURL } = state['features/base/connection'];
|
||||
|
||||
return {
|
||||
|
|
|
@ -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<Props> {
|
|||
_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<Props> {
|
|||
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<Props> {
|
|||
* _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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
export * from './actions';
|
||||
export * from './components';
|
||||
|
||||
import './middleware';
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<Props, State> {
|
||||
/**
|
||||
* Constructor of the component.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
pageIndex: DEFAULT_PAGE
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Props, State> {
|
||||
/**
|
||||
* 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 (
|
||||
<View
|
||||
style = { [
|
||||
styles.pagedListContainer,
|
||||
disabled ? styles.pagedListContainerDisabled : null
|
||||
] }>
|
||||
{
|
||||
(this._calendarEnabled && this._renderPagedList(disabled))
|
||||
|| <RecentList
|
||||
disabled = { disabled }
|
||||
style = { styles.pagedList } />
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderPagedList: boolean => Object
|
||||
|
||||
}
|
|
@ -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 (
|
||||
<View
|
||||
style = { [
|
||||
styles.pagedListContainer,
|
||||
disabled ? styles.pagedListContainerDisabled : null
|
||||
] }>
|
||||
<View style = { styles.pagedListContainer }>
|
||||
<ViewPagerAndroid
|
||||
initialPage = { DEFAULT_PAGE }
|
||||
onPageSelected = { this._onPageSelected }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { View, TabBarIOS } from 'react-native';
|
||||
import { TabBarIOS } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
|
@ -31,39 +31,35 @@ 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() {
|
||||
_renderPagedList(disabled) {
|
||||
const { pageIndex } = this.state;
|
||||
const { disabled, t } = this.props;
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<View
|
||||
style = { [
|
||||
styles.pagedListContainer,
|
||||
disabled ? styles.pagedListContainerDisabled : null
|
||||
] }>
|
||||
<TabBarIOS
|
||||
itemPositioning = 'fill'
|
||||
style = { styles.pagedList }>
|
||||
<TabBarIOS.Item
|
||||
onPress = { this._onTabSelected(0) }
|
||||
selected = { pageIndex === 0 }
|
||||
systemIcon = 'history' >
|
||||
<RecentList disabled = { disabled } />
|
||||
</TabBarIOS.Item>
|
||||
<TabBarIOS.Item
|
||||
icon = { CALENDAR_ICON }
|
||||
onPress = { this._onTabSelected(1) }
|
||||
selected = { pageIndex === 1 }
|
||||
title = { t('welcomepage.calendar') } >
|
||||
<MeetingList
|
||||
disabled = { disabled } />
|
||||
</TabBarIOS.Item>
|
||||
</TabBarIOS>
|
||||
</View>
|
||||
<TabBarIOS
|
||||
itemPositioning = 'fill'
|
||||
style = { styles.pagedList }>
|
||||
<TabBarIOS.Item
|
||||
onPress = { this._onTabSelected(0) }
|
||||
selected = { pageIndex === 0 }
|
||||
systemIcon = 'history' >
|
||||
<RecentList disabled = { disabled } />
|
||||
</TabBarIOS.Item>
|
||||
<TabBarIOS.Item
|
||||
icon = { CALENDAR_ICON }
|
||||
onPress = { this._onTabSelected(1) }
|
||||
selected = { pageIndex === 1 }
|
||||
title = { t('welcomepage.calendar') } >
|
||||
<MeetingList
|
||||
disabled = { disabled } />
|
||||
</TabBarIOS.Item>
|
||||
</TabBarIOS>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue