diff --git a/src/components/Screens/WebSectionList.js b/src/components/Screens/WebSectionList.js index 5b72c62..fdaa7b2 100644 --- a/src/components/Screens/WebSectionList.js +++ b/src/components/Screens/WebSectionList.js @@ -10,26 +10,28 @@ import BasicLoadingScreen from "./BasicLoadingScreen"; import {withCollapsible} from "../../utils/withCollapsible"; import * as Animatable from 'react-native-animatable'; import CustomTabBar from "../Tabbar/CustomTabBar"; +import {Collapsible} from "react-navigation-collapsible"; type Props = { - navigation: Object, + navigation: { [key: string]: any }, fetchUrl: string, autoRefreshTime: number, refreshOnFocus: boolean, - renderItem: React.Node, - renderSectionHeader: React.Node, - stickyHeader: boolean, - createDataset: Function, - updateData: number, - itemHeight: number | null, - onScroll: Function, - collapsibleStack: Object, + renderItem: (data: { [key: string]: any }) => React.Node, + createDataset: (data: { [key: string]: any }) => Array, + onScroll: (event: SyntheticEvent) => void, + collapsibleStack: Collapsible, + + itemHeight?: number, + updateData?: number, + renderSectionHeader?: (data: { [key: string]: any }) => React.Node, + stickyHeader?: boolean, } type State = { refreshing: boolean, firstLoading: boolean, - fetchedData: ?Object, + fetchedData: { [key: string]: any } | null, snackbarVisible: boolean }; @@ -45,37 +47,21 @@ const MIN_REFRESH_TIME = 5 * 1000; class WebSectionList extends React.PureComponent { static defaultProps = { - renderSectionHeader: null, stickyHeader: false, updateData: 0, - itemHeight: null, }; - scrollRef: Object; + scrollRef: { current: null | Animated.SectionList }; refreshInterval: IntervalID; - lastRefresh: Date; + lastRefresh: Date | null; state = { refreshing: false, firstLoading: true, - fetchedData: undefined, + fetchedData: null, snackbarVisible: false }; - onRefresh: Function; - onFetchSuccess: Function; - onFetchError: Function; - getEmptySectionHeader: Function; - - constructor() { - super(); - // creating references to functions used in render() - this.onRefresh = this.onRefresh.bind(this); - this.onFetchSuccess = this.onFetchSuccess.bind(this); - this.onFetchError = this.onFetchError.bind(this); - this.getEmptySectionHeader = this.getEmptySectionHeader.bind(this); - } - /** * Registers react navigation events on first screen load. * Allows to detect when the screen is focused @@ -87,13 +73,14 @@ class WebSectionList extends React.PureComponent { this.props.navigation.addListener('blur', onScreenBlur); this.scrollRef = React.createRef(); this.onRefresh(); + this.lastRefresh = null; } /** * Refreshes data when focusing the screen and setup a refresh interval if asked to */ onScreenFocus() { - if (this.props.refreshOnFocus && this.lastRefresh !== undefined) + if (this.props.refreshOnFocus && this.lastRefresh) this.onRefresh(); if (this.props.autoRefreshTime > 0) this.refreshInterval = setInterval(this.onRefresh, this.props.autoRefreshTime) @@ -115,36 +102,37 @@ class WebSectionList extends React.PureComponent { * * @param fetchedData The newly fetched data */ - onFetchSuccess(fetchedData: Object) { + onFetchSuccess = (fetchedData: { [key: string]: any }) => { this.setState({ fetchedData: fetchedData, refreshing: false, firstLoading: false }); this.lastRefresh = new Date(); - } + }; /** * Callback used when fetch encountered an error. * It will reset the displayed data and show an error. */ - onFetchError() { + onFetchError = () => { this.setState({ - fetchedData: undefined, + fetchedData: null, refreshing: false, firstLoading: false }); this.showSnackBar(); - } + }; /** * Refreshes data and shows an animations while doing it */ - onRefresh() { + onRefresh = () => { let canRefresh; - if (this.lastRefresh !== undefined) - canRefresh = (new Date().getTime() - this.lastRefresh.getTime()) > MIN_REFRESH_TIME; - else + if (this.lastRefresh != null) { + const last = this.lastRefresh; + canRefresh = (new Date().getTime() - last.getTime()) > MIN_REFRESH_TIME; + } else canRefresh = true; if (canRefresh) { this.setState({refreshing: true}); @@ -152,17 +140,7 @@ class WebSectionList extends React.PureComponent { .then(this.onFetchSuccess) .catch(this.onFetchError); } - } - - /** - * Gets an empty section header - * - * @param section The current section - * @return {*} - */ - getEmptySectionHeader({section}: Object) { - return ; - } + }; /** * Shows the error popup @@ -174,25 +152,38 @@ class WebSectionList extends React.PureComponent { */ hideSnackBar = () => this.setState({snackbarVisible: false}); - itemLayout = (data: Object, index: number) => ({ - length: this.props.itemHeight, - offset: this.props.itemHeight * index, - index - }); + itemLayout = (data: { [key: string]: any }, index: number) => { + const height = this.props.itemHeight; + if (height == null) + return undefined; + return { + length: height, + offset: height * index, + index + } + }; - renderSectionHeader = (data: Object) => { - return ( - - {this.props.renderSectionHeader(data)} - - ); + renderSectionHeader = (data: { section: { [key: string]: any } }) => { + if (this.props.renderSectionHeader != null) { + return ( + + {this.props.renderSectionHeader(data)} + + ); + } else + return null; } - renderItem = (data: Object) => { + renderItem = (data: { + item: { [key: string]: any }, + index: number, + section: { [key: string]: any }, + separators: { [key: string]: any }, + }) => { return ( { ); } - onScroll = (event: Object) => { + onScroll = (event: SyntheticEvent) => { if (this.props.onScroll) this.props.onScroll(event); } render() { let dataset = []; - if (this.state.fetchedData !== undefined) + if (this.state.fetchedData != null) dataset = this.props.createDataset(this.state.fetchedData); - const shouldRenderHeader = this.props.renderSectionHeader !== null; const {containerPaddingTop, scrollIndicatorInsetTop, onScrollWithListener} = this.props.collapsibleStack; return ( @@ -230,7 +220,7 @@ class WebSectionList extends React.PureComponent { /> } //$FlowFixMe - renderSectionHeader={shouldRenderHeader ? this.renderSectionHeader : this.getEmptySectionHeader} + renderSectionHeader={this.renderSectionHeader} //$FlowFixMe renderItem={this.renderItem} stickySectionHeadersEnabled={this.props.stickyHeader} @@ -242,7 +232,7 @@ class WebSectionList extends React.PureComponent { errorCode={ERROR_TYPE.CONNECTION_ERROR} onRefresh={this.onRefresh}/> } - getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined} + getItemLayout={this.props.itemHeight != null ? this.itemLayout : undefined} // Animations onScroll={onScrollWithListener(this.onScroll)} contentContainerStyle={{