Add pull-to-refresh functionality

This commit is contained in:
zbettenbuk 2018-02-14 10:50:48 -06:00 committed by Lyubo Marinov
parent cb973b61aa
commit 4b17c6f015
6 changed files with 90 additions and 19 deletions

View File

@ -22,6 +22,11 @@ type Props = {
*/
onPress: Function,
/**
* Function to be invoked when pull-to-refresh is performed.
*/
onRefresh: Function,
/**
* Sections to be rendered in the following format:
*
@ -60,6 +65,7 @@ export default class NavigateSectionList extends Component<Props> {
this._getAvatarColor = this._getAvatarColor.bind(this);
this._getItemKey = this._getItemKey.bind(this);
this._onPress = this._onPress.bind(this);
this._onRefresh = this._onRefresh.bind(this);
this._renderItem = this._renderItem.bind(this);
this._renderItemLine = this._renderItemLine.bind(this);
this._renderItemLines = this._renderItemLines.bind(this);
@ -68,6 +74,8 @@ export default class NavigateSectionList extends Component<Props> {
/**
* Implements React's Component.render function.
* Note: we don't use the refreshing value yet, because refreshing of these
* lists is super quick, no need to complicate the code - yet.
*
* @inheritdoc
*/
@ -79,6 +87,8 @@ export default class NavigateSectionList extends Component<Props> {
style = { styles.container } >
<SectionList
keyExtractor = { this._getItemKey }
onRefresh = { this._onRefresh }
refreshing = { false }
renderItem = { this._renderItem }
renderSectionHeader = { this._renderSection }
sections = { sections }
@ -158,6 +168,22 @@ export default class NavigateSectionList extends Component<Props> {
};
}
_onRefresh: () => void
/**
* Invokes the onRefresh callback if present.
*
* @private
* @returns {void}
*/
_onRefresh() {
const { onRefresh } = this.props;
if (typeof onRefresh === 'function') {
onRefresh();
}
}
_renderItem: Object => Object;
/**

View File

@ -71,7 +71,7 @@ const HEADER_STYLES = {
}
};
const SECTIONLIST_STYLES = {
const SECTION_LIST_STYLES = {
/**
* The style of the actual avatar.
*/
@ -229,6 +229,6 @@ const SIDEBAR_STYLES = {
*/
export default createStyleSheet({
...HEADER_STYLES,
...SECTIONLIST_STYLES,
...SECTION_LIST_STYLES,
...SIDEBAR_STYLES
});

View File

@ -9,3 +9,9 @@ export const NEW_CALENDAR_ENTRY_LIST = Symbol('NEW_CALENDAR_ENTRY_LIST');
* Action to add a new known domain to the list.
*/
export const NEW_KNOWN_DOMAIN = Symbol('NEW_KNOWN_DOMAIN');
/**
* Action to refresh (re-fetch) the entry list.
*/
export const REFRESH_CALENDAR_ENTRY_LIST
= Symbol('REFRESH_CALENDAR_ENTRY_LIST');

View File

@ -1,21 +1,9 @@
// @flow
import { NEW_CALENDAR_ENTRY_LIST, NEW_KNOWN_DOMAIN } from './actionTypes';
/**
* Sends an action to update the current calendar list in redux.
*
* @param {Array<Object>} events - The new list.
* @returns {{
* type: NEW_CALENDAR_ENTRY_LIST,
* events: Array<Object>
* }}
*/
export function updateCalendarEntryList(events: Array<Object>) {
return {
type: NEW_CALENDAR_ENTRY_LIST,
events
};
}
import {
NEW_CALENDAR_ENTRY_LIST,
NEW_KNOWN_DOMAIN,
REFRESH_CALENDAR_ENTRY_LIST
} from './actionTypes';
/**
* Sends an action to add a new known domain if not present yet.
@ -32,3 +20,32 @@ export function maybeAddNewKnownDomain(domainName: string) {
domainName
};
}
/**
* Sends an action to refresh the entry list (fetches new data).
*
* @returns {{
* type: REFRESH_CALENDAR_ENTRY_LIST
* }}
*/
export function refreshCalendarEntryList() {
return {
type: REFRESH_CALENDAR_ENTRY_LIST
};
}
/**
* Sends an action to update the current calendar list in redux.
*
* @param {Array<Object>} events - The new list.
* @returns {{
* type: NEW_CALENDAR_ENTRY_LIST,
* events: Array<Object>
* }}
*/
export function updateCalendarEntryList(events: Array<Object>) {
return {
type: NEW_CALENDAR_ENTRY_LIST,
events
};
}

View File

@ -2,6 +2,8 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { refreshCalendarEntryList } from '../actions';
import { appNavigate } from '../../app';
import { translate } from '../../base/i18n';
import { NavigateSectionList } from '../../base/react';
@ -51,6 +53,7 @@ class MeetingList extends Component<Props> {
super(props);
this._onPress = this._onPress.bind(this);
this._onRefresh = this._onRefresh.bind(this);
this._toDisplayableItem = this._toDisplayableItem.bind(this);
this._toDisplayableList = this._toDisplayableList.bind(this);
this._toDateString = this._toDateString.bind(this);
@ -68,6 +71,7 @@ class MeetingList extends Component<Props> {
<NavigateSectionList
disabled = { disabled }
onPress = { this._onPress }
onRefresh = { this._onRefresh }
sections = { this._toDisplayableList() } />
);
}
@ -87,6 +91,20 @@ class MeetingList extends Component<Props> {
dispatch(appNavigate(url));
}
_onRefresh: () => void
/**
* Callback to execute when the list is doing a pull-to-refresh.
*
* @private
* @returns {void}
*/
_onRefresh() {
const { dispatch } = this.props;
dispatch(refreshCalendarEntryList());
}
_toDisplayableItem: Object => Object
/**

View File

@ -9,6 +9,7 @@ import { parseURIString } from '../base/util';
import { APP_WILL_MOUNT } from '../app';
import { maybeAddNewKnownDomain, updateCalendarEntryList } from './actions';
import { REFRESH_CALENDAR_ENTRY_LIST } from './actionTypes';
const FETCH_END_DAYS = 10;
const FETCH_START_DAYS = -1;
@ -23,6 +24,9 @@ MiddlewareRegistry.register(store => next => action => {
_ensureDefaultServer(store);
_fetchCalendarEntries(store);
break;
case REFRESH_CALENDAR_ENTRY_LIST:
_fetchCalendarEntries(store);
break;
case SET_ROOM:
_parseAndAddDomain(store);
}