More generic way to refresh lists on the welcome screen
This commit is contained in:
parent
374e3ccf2c
commit
63c165ee8b
|
@ -35,14 +35,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
dispatch: Function,
|
dispatch: Function,
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells the component if it's being displayed at the moment, or not. Note:
|
|
||||||
* as an example, on Android it can happen that the component is rendered
|
|
||||||
* but not displayed, because components like ViewPagerAndroid render their
|
|
||||||
* children even if they are not visible at the moment.
|
|
||||||
*/
|
|
||||||
displayed: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The translate function.
|
* The translate function.
|
||||||
*/
|
*/
|
||||||
|
@ -85,12 +77,6 @@ class MeetingList extends Component<Props> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const { dispatch, displayed } = props;
|
|
||||||
|
|
||||||
if (displayed) {
|
|
||||||
dispatch(refreshCalendar());
|
|
||||||
}
|
|
||||||
|
|
||||||
this._getRenderListEmptyComponent
|
this._getRenderListEmptyComponent
|
||||||
= this._getRenderListEmptyComponent.bind(this);
|
= this._getRenderListEmptyComponent.bind(this);
|
||||||
this._onPress = this._onPress.bind(this);
|
this._onPress = this._onPress.bind(this);
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import { isCalendarEnabled } from '../../calendar-sync';
|
|
||||||
|
import { MeetingList } from '../../calendar-sync';
|
||||||
import { RecentList } from '../../recent-list';
|
import { RecentList } from '../../recent-list';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -28,7 +29,7 @@ type Props = {
|
||||||
* The i18n translate function
|
* The i18n translate function
|
||||||
*/
|
*/
|
||||||
t: Function
|
t: Function
|
||||||
}
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
|
||||||
|
@ -36,16 +37,16 @@ type State = {
|
||||||
* The currently selected page.
|
* The currently selected page.
|
||||||
*/
|
*/
|
||||||
pageIndex: number
|
pageIndex: number
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for the platform specific paged lists.
|
* Abstract class for the platform specific paged lists.
|
||||||
*/
|
*/
|
||||||
export default class AbstractPagedList extends Component<Props, State> {
|
export default class AbstractPagedList extends Component<Props, State> {
|
||||||
/**
|
/**
|
||||||
* True if the calendar feature is enabled on the platform, false otherwise.
|
* The list of pages displayed in the component, referenced by page index.
|
||||||
*/
|
*/
|
||||||
_calendarEnabled: boolean
|
_pages: Array<Object>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of the component.
|
* Constructor of the component.
|
||||||
|
@ -55,7 +56,13 @@ export default class AbstractPagedList extends Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this._calendarEnabled = isCalendarEnabled();
|
this._pages = [];
|
||||||
|
for (const component of [ RecentList, MeetingList ]) {
|
||||||
|
// XXX Certain pages may be contributed by optional features. For
|
||||||
|
// example, MeetingList is contributed by the calendar feature and
|
||||||
|
// apps i.e. SDK consumers may not enable the calendar feature.
|
||||||
|
component && this._pages.push(component);
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
pageIndex: DEFAULT_PAGE
|
pageIndex: DEFAULT_PAGE
|
||||||
|
@ -77,15 +84,43 @@ export default class AbstractPagedList extends Component<Props, State> {
|
||||||
disabled ? styles.pagedListContainerDisabled : null
|
disabled ? styles.pagedListContainerDisabled : null
|
||||||
] }>
|
] }>
|
||||||
{
|
{
|
||||||
(this._calendarEnabled && this._renderPagedList(disabled))
|
this._pages.length > 1
|
||||||
|| <RecentList
|
? this._renderPagedList(disabled)
|
||||||
disabled = { disabled }
|
: React.createElement(
|
||||||
style = { styles.pagedList } />
|
/* type */ this._pages[0],
|
||||||
|
/* props */ {
|
||||||
|
disabled,
|
||||||
|
style: styles.pagedList
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderPagedList: boolean => Object
|
_renderPagedList: boolean => React$Node;
|
||||||
|
|
||||||
|
_selectPage: number => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the selected page.
|
||||||
|
*
|
||||||
|
* @param {number} pageIndex - The index of the active page.
|
||||||
|
* @protected
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_selectPage(pageIndex: number) {
|
||||||
|
this.setState({
|
||||||
|
pageIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
// The page's Component may have a refresh(dispatch) function which we
|
||||||
|
// invoke when the page is selected.
|
||||||
|
const selectedPageComponent = this._pages[pageIndex];
|
||||||
|
|
||||||
|
if (selectedPageComponent) {
|
||||||
|
const { refresh } = selectedPageComponent;
|
||||||
|
|
||||||
|
typeof refresh === 'function' && refresh(this.props.dispatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, TouchableOpacity, View, ViewPagerAndroid } from 'react-native';
|
import { Text, TouchableOpacity, View, ViewPagerAndroid } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { Icon } from '../../base/font-icons';
|
import { Icon } from '../../base/font-icons';
|
||||||
import { MeetingList } from '../../calendar-sync';
|
import { MeetingList } from '../../calendar-sync';
|
||||||
|
@ -14,24 +16,74 @@ import styles from './styles';
|
||||||
*
|
*
|
||||||
* @extends PagedList
|
* @extends PagedList
|
||||||
*/
|
*/
|
||||||
export default class PagedList extends AbstractPagedList {
|
class PagedList extends AbstractPagedList {
|
||||||
/**
|
/**
|
||||||
* A reference to the viewpager.
|
* A reference to the viewpager.
|
||||||
*/
|
*/
|
||||||
_viewPager: Object;
|
_viewPager: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of the PagedList Component.
|
* Initializes a new {@code PagedList} instance.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._getIndicatorStyle = this._getIndicatorStyle.bind(this);
|
this._getIndicatorStyle = this._getIndicatorStyle.bind(this);
|
||||||
this._onPageSelected = this._onPageSelected.bind(this);
|
this._onPageSelected = this._onPageSelected.bind(this);
|
||||||
this._onSelectPage = this._onSelectPage.bind(this);
|
this._onSelectPage = this._onSelectPage.bind(this);
|
||||||
this._setPagerReference = this._setPagerReference.bind(this);
|
this._setViewPager = this._setViewPager.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getIndicatorStyle: number => Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the style of an indicator.
|
||||||
|
*
|
||||||
|
* @param {number} indicatorIndex - The index of the indicator.
|
||||||
|
* @private
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
_getIndicatorStyle(indicatorIndex) {
|
||||||
|
if (this.state.pageIndex === indicatorIndex) {
|
||||||
|
return styles.pageIndicatorTextActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPageSelected: Object => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the index of the currently selected page.
|
||||||
|
*
|
||||||
|
* @param {Object} event - The native event of the callback.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onPageSelected({ nativeEvent: { position } }) {
|
||||||
|
if (this.state.pageIndex !== position) {
|
||||||
|
this._selectPage(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSelectPage: number => Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a function to be used as a callback for the tab bar.
|
||||||
|
*
|
||||||
|
* @param {number} pageIndex - The index of the page to activate via the
|
||||||
|
* callback.
|
||||||
|
* @private
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
_onSelectPage(pageIndex) {
|
||||||
|
return () => {
|
||||||
|
this._viewPager.setPage(pageIndex);
|
||||||
|
this._selectPage(pageIndex);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,23 +94,19 @@ export default class PagedList extends AbstractPagedList {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
_renderPagedList(disabled) {
|
_renderPagedList(disabled) {
|
||||||
const { pageIndex } = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style = { styles.pagedListContainer }>
|
<View style = { styles.pagedListContainer }>
|
||||||
<ViewPagerAndroid
|
<ViewPagerAndroid
|
||||||
initialPage = { DEFAULT_PAGE }
|
initialPage = { DEFAULT_PAGE }
|
||||||
onPageSelected = { this._onPageSelected }
|
onPageSelected = { this._onPageSelected }
|
||||||
peekEnabled = { true }
|
peekEnabled = { true }
|
||||||
ref = { this._setPagerReference }
|
ref = { this._setViewPager }
|
||||||
style = { styles.pagedList }>
|
style = { styles.pagedList }>
|
||||||
<View key = { 0 }>
|
<View key = { 0 }>
|
||||||
<RecentList disabled = { disabled } />
|
<RecentList disabled = { disabled } />
|
||||||
</View>
|
</View>
|
||||||
<View key = { 1 }>
|
<View key = { 1 }>
|
||||||
<MeetingList
|
<MeetingList disabled = { disabled } />
|
||||||
disabled = { disabled }
|
|
||||||
displayed = { pageIndex === 1 } />
|
|
||||||
</View>
|
</View>
|
||||||
</ViewPagerAndroid>
|
</ViewPagerAndroid>
|
||||||
<View style = { styles.pageIndicatorContainer }>
|
<View style = { styles.pageIndicatorContainer }>
|
||||||
|
@ -107,69 +155,19 @@ export default class PagedList extends AbstractPagedList {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getIndicatorStyle: number => Object;
|
_setViewPager: Object => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the style of an indicator.
|
* Sets the {@link ViewPagerAndroid} instance.
|
||||||
*
|
*
|
||||||
|
* @param {ViewPagerAndroid} viewPager - The {@code ViewPagerAndroid}
|
||||||
|
* instance.
|
||||||
* @private
|
* @private
|
||||||
* @param {number} indicatorIndex - The index of the indicator.
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
_getIndicatorStyle(indicatorIndex) {
|
|
||||||
if (this.state.pageIndex === indicatorIndex) {
|
|
||||||
return styles.pageIndicatorTextActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPageSelected: Object => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the index of the currently selected page.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} event - The native event of the callback.
|
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPageSelected({ nativeEvent: { position } }) {
|
_setViewPager(viewPager) {
|
||||||
if (this.state.pageIndex !== position) {
|
this._viewPager = viewPager;
|
||||||
this.setState({
|
|
||||||
pageIndex: position
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSelectPage: number => Function
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a function to be used as a callback for the tab bar.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {number} pageIndex - The index of the page to activate via the
|
|
||||||
* callback.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
_onSelectPage(pageIndex) {
|
|
||||||
return () => {
|
|
||||||
this._viewPager.setPage(pageIndex);
|
|
||||||
this.setState({
|
|
||||||
pageIndex
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_setPagerReference: Object => void
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pager's reference for direct modification.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {React@Node} component - The pager component.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_setPagerReference(component) {
|
|
||||||
this._viewPager = component;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default connect()(PagedList);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { TabBarIOS } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import { MeetingList, refreshCalendar } from '../../calendar-sync';
|
import { MeetingList } from '../../calendar-sync';
|
||||||
import { RecentList } from '../../recent-list';
|
import { RecentList } from '../../recent-list';
|
||||||
|
|
||||||
import AbstractPagedList from './AbstractPagedList';
|
import AbstractPagedList from './AbstractPagedList';
|
||||||
|
@ -21,15 +21,30 @@ const CALENDAR_ICON = require('../../../../images/calendar.png');
|
||||||
class PagedList extends AbstractPagedList {
|
class PagedList extends AbstractPagedList {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of the PagedList Component.
|
* Initializes a new {@code PagedList} instance.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._onTabSelected = this._onTabSelected.bind(this);
|
this._onTabSelected = this._onTabSelected.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onTabSelected: number => Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a callback to update the selected tab.
|
||||||
|
*
|
||||||
|
* @param {number} tabIndex - The selected tab.
|
||||||
|
* @private
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
_onTabSelected(tabIndex) {
|
||||||
|
return () => super._selectPage(tabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the entire paged list if calendar is enabled.
|
* Renders the entire paged list if calendar is enabled.
|
||||||
*
|
*
|
||||||
|
@ -48,46 +63,19 @@ class PagedList extends AbstractPagedList {
|
||||||
<TabBarIOS.Item
|
<TabBarIOS.Item
|
||||||
onPress = { this._onTabSelected(0) }
|
onPress = { this._onTabSelected(0) }
|
||||||
selected = { pageIndex === 0 }
|
selected = { pageIndex === 0 }
|
||||||
systemIcon = 'history' >
|
systemIcon = 'history'>
|
||||||
<RecentList disabled = { disabled } />
|
<RecentList disabled = { disabled } />
|
||||||
</TabBarIOS.Item>
|
</TabBarIOS.Item>
|
||||||
<TabBarIOS.Item
|
<TabBarIOS.Item
|
||||||
icon = { CALENDAR_ICON }
|
icon = { CALENDAR_ICON }
|
||||||
onPress = { this._onTabSelected(1) }
|
onPress = { this._onTabSelected(1) }
|
||||||
selected = { pageIndex === 1 }
|
selected = { pageIndex === 1 }
|
||||||
title = { t('welcomepage.calendar') } >
|
title = { t('welcomepage.calendar') }>
|
||||||
<MeetingList
|
<MeetingList disabled = { disabled } />
|
||||||
disabled = { disabled } />
|
|
||||||
</TabBarIOS.Item>
|
</TabBarIOS.Item>
|
||||||
</TabBarIOS>
|
</TabBarIOS>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTabSelected: number => Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a callback to update the selected tab.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {number} tabIndex - The selected tab.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
_onTabSelected(tabIndex) {
|
|
||||||
return () => {
|
|
||||||
this.setState({
|
|
||||||
pageIndex: tabIndex
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tabIndex === 1) {
|
|
||||||
/**
|
|
||||||
* This is a workaround as TabBarIOS doesn't invoke
|
|
||||||
* componentWillReciveProps on prop change of the MeetingList
|
|
||||||
* component.
|
|
||||||
*/
|
|
||||||
this.props.dispatch(refreshCalendar());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate(connect()(PagedList));
|
export default translate(connect()(PagedList));
|
||||||
|
|
Loading…
Reference in New Issue