| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // @flow
-
- import React, { Component } from 'react';
-
- // TODO: Maybe try to make all NavigateSectionList components to work for both
- // mobile and web, and move them to NavigateSectionList component.
- import {
- NavigateSectionListEmptyComponent,
- NavigateSectionListItem,
- NavigateSectionListSectionHeader,
- SectionList
- } from './_';
- import type { Section } from '../Types';
-
- type Props = {
-
- /**
- * Indicates if the list is disabled or not.
- */
- disabled: boolean,
-
- /**
- * Function to be invoked when an item is pressed. The item's URL is passed.
- */
- onPress: Function,
-
- /**
- * Function to be invoked when pull-to-refresh is performed.
- */
- onRefresh: Function,
-
- /**
- * Function to be invoked when a secondary action is performed on an item.
- * The item's ID is passed.
- */
- onSecondaryAction: Function,
-
- /**
- * Function to override the rendered default empty list component.
- */
- renderListEmptyComponent: Function,
-
- /**
- * An array of sections
- */
- sections: Array<Section>,
-
- /**
- * Optional array of on-slide actions this list should support. For details
- * see https://github.com/dancormier/react-native-swipeout.
- */
- slideActions?: Array<Object>
- };
-
- /**
- * Implements a general section list to display items that have a URL property
- * and navigates to (probably) meetings, such as the recent list or the meeting
- * list components.
- */
- class NavigateSectionList extends Component<Props> {
- /**
- * Creates an empty section object.
- *
- * @param {string} title - The title of the section.
- * @param {string} key - The key of the section. It must be unique.
- * @private
- * @returns {Object}
- */
- static createSection(title: string, key: string) {
- return {
- data: [],
- key,
- title
- };
- }
-
- /**
- * Constructor of the NavigateSectionList component.
- *
- * @inheritdoc
- */
- constructor(props: Props) {
- super(props);
- 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._renderListEmptyComponent
- = this._renderListEmptyComponent.bind(this);
- this._renderSectionHeader = this._renderSectionHeader.bind(this);
- }
-
- /**
- * Implements React's {@code Component.render}.
- * 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
- */
- render() {
- const {
- renderListEmptyComponent = this._renderListEmptyComponent(),
- sections
- } = this.props;
-
- return (
- <SectionList
- ListEmptyComponent = { renderListEmptyComponent }
- keyExtractor = { this._getItemKey }
- onItemClick = { this.props.onPress }
- onRefresh = { this._onRefresh }
- refreshing = { false }
- renderItem = { this._renderItem }
- renderSectionHeader = { this._renderSectionHeader }
- sections = { sections } />
- );
- }
-
- _getItemKey: (Object, number) => string;
-
- /**
- * Generates a unique id to every item.
- *
- * @param {Object} item - The item.
- * @param {number} index - The item index.
- * @private
- * @returns {string}
- */
- _getItemKey(item, index) {
- return `${index}-${item.key}`;
- }
-
- _onPress: string => Function;
-
- /**
- * Returns a function that is used in the onPress callback of the items.
- *
- * @param {string} url - The URL of the item to navigate to.
- * @private
- * @returns {Function}
- */
- _onPress(url) {
- const { disabled, onPress } = this.props;
-
- if (!disabled && url && typeof onPress === 'function') {
- return () => onPress(url);
- }
-
- return null;
- }
-
- _onRefresh: () => void;
-
- /**
- * Invokes the onRefresh callback if present.
- *
- * @private
- * @returns {void}
- */
- _onRefresh() {
- const { onRefresh } = this.props;
-
- if (typeof onRefresh === 'function') {
- onRefresh();
- }
- }
-
- _onSecondaryAction: Object => Function;
-
- /**
- * Returns a function that is used in the secondaryAction callback of the
- * items.
- *
- * @param {string} id - The id of the item that secondary action was
- * performed on.
- * @private
- * @returns {Function}
- */
- _onSecondaryAction(id) {
- return () => {
- this.props.onSecondaryAction(id);
- };
- }
-
- _renderItem: Object => Object;
-
- /**
- * Renders a single item in the list.
- *
- * @param {Object} listItem - The item to render.
- * @param {string} key - The item needed for rendering using map on web.
- * @private
- * @returns {Component}
- */
- _renderItem(listItem, key: string = '') {
- const { item } = listItem;
- const { id, url } = item;
-
- // XXX The value of title cannot be undefined; otherwise, react-native
- // will throw a TypeError: Cannot read property of undefined. While it's
- // difficult to get an undefined title and very likely requires the
- // execution of incorrect source code, it is undesirable to break the
- // whole app because of an undefined string.
- if (typeof item.title === 'undefined') {
- return null;
- }
-
- return (
- <NavigateSectionListItem
- item = { item }
- key = { key }
- onPress = { url ? this._onPress(url) : undefined }
- secondaryAction = {
- url ? undefined : this._onSecondaryAction(id) }
- slideActions = { this.props.slideActions } />
- );
- }
-
- _renderListEmptyComponent: () => Object;
-
- /**
- * Renders a component to display when the list is empty.
- *
- * @param {Object} section - The section being rendered.
- * @private
- * @returns {React$Node}
- */
- _renderListEmptyComponent() {
- const { onRefresh } = this.props;
-
- if (typeof onRefresh === 'function') {
- return (
- <NavigateSectionListEmptyComponent />
- );
- }
-
- return null;
- }
-
- _renderSectionHeader: Object => Object;
-
- /**
- * Renders a section header.
- *
- * @param {Object} section - The section being rendered.
- * @private
- * @returns {React$Node}
- */
- _renderSectionHeader(section) {
- return (
- <NavigateSectionListSectionHeader
- section = { section } />
- );
- }
- }
-
- export default NavigateSectionList;
|