// @flow import * as React from 'react'; import {FlatList} from "react-native"; import {Drawer, List, withTheme} from 'react-native-paper'; import {Linking} from "expo"; import Collapsible from "react-native-collapsible"; import * as Animatable from "react-native-animatable"; import {View} from "react-native-animatable"; type Props = { navigation: Object, startOpen: boolean, isLoggedIn: boolean, sectionName: string, activeRoute: string, listKey: string, listData: Array, } type State = { expanded: boolean } const AnimatedListIcon = Animatable.createAnimatableComponent(List.Icon); const LIST_ITEM_HEIGHT = 48; class SideBarSection extends React.PureComponent { state = { expanded: this.props.startOpen, }; colors: Object; shouldExpand: boolean; chevronRef: Object; constructor(props) { super(props); this.colors = props.theme.colors; this.chevronRef = React.createRef(); } /** * Searches if the current route is contained in the given list data. * If this is the case and the list is collapsed, we should expand this list. * * @return boolean */ shouldExpandList() { for (let i = 0; i < this.props.listData.length; i++) { if (this.props.listData[i].route === this.props.activeRoute) { return this.state.expanded === false; } } return false; } /** * Callback when a drawer item is pressed. * It will either navigate to the associated screen, or open the browser to the associated link * * @param item The item pressed */ onListItemPress(item: Object) { if (item.link !== undefined) Linking.openURL(item.link); else if (item.action !== undefined) item.action(); else this.props.navigation.navigate(item.route); } /** * Key extractor for list items * * @param item The item to extract the key from * @return {string} The extracted key */ listKeyExtractor = (item: Object) => item.route; shouldHideItem(item: Object) { const onlyWhenLoggedOut = item.onlyWhenLoggedOut !== undefined && item.onlyWhenLoggedOut === true; const onlyWhenLoggedIn = item.onlyWhenLoggedIn !== undefined && item.onlyWhenLoggedIn === true; return (onlyWhenLoggedIn && !this.props.isLoggedIn || onlyWhenLoggedOut && this.props.isLoggedIn); } /** * Gets the render item for the given list item * * @param item The item to render * @return {*} */ getRenderItem = ({item}: Object) => { const onListItemPress = this.onListItemPress.bind(this, item); if (this.shouldHideItem(item)) return null; return ( ); }; toggleAccordion = () => { if ((!this.state.expanded && this.shouldExpand) || !this.shouldExpand) { this.chevronRef.current.transitionTo({ rotate: this.state.expanded ? '0deg' : '180deg' }); this.setState({expanded: !this.state.expanded}) } }; shouldRenderAccordion() { let itemsToRender = 0; for (let i = 0; i < this.props.listData.length; i++) { if (!this.shouldHideItem(this.props.listData[i])) itemsToRender += 1; } return itemsToRender > 1; } itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index}); getFlatList() { return ( // $FlowFixMe ); } render() { if (this.shouldRenderAccordion()) { this.shouldExpand = this.shouldExpandList(); if (this.shouldExpand) this.toggleAccordion(); return ( } /> {this.getFlatList()} ); } else return this.getFlatList(); } } export default withTheme(SideBarSection);