diff --git a/locales/en.json b/locales/en.json index 58a55b2..dd82a4e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -95,8 +95,10 @@ }, "home": { "title": "Campus", - "feedTitle": "Amicale's News", + "feedTitle": "Campus News", "feed": "Details", + "feedLoading": "Loading News", + "feedError": "Failed to load news", "dashboard": { "seeMore": "Click to see more", "todayEventsTitle": "Today's events", diff --git a/locales/fr.json b/locales/fr.json index 5244157..34152a1 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -95,8 +95,10 @@ }, "home": { "title": "Campus", - "feedTitle": "News de l'Amicale", + "feedTitle": "News du Campus", "feed": "Détails", + "feedLoading": "Chargement des news", + "feedError": "Erreur de chargement des news", "dashboard": { "seeMore": "Clique pour plus d'infos", "todayEventsTitle": "Événements aujourd'hui", diff --git a/src/components/Screens/WebSectionList.js b/src/components/Screens/WebSectionList.js index afb7c7d..7b8f9d2 100644 --- a/src/components/Screens/WebSectionList.js +++ b/src/components/Screens/WebSectionList.js @@ -11,21 +11,23 @@ import {withCollapsible} from "../../utils/withCollapsible"; import * as Animatable from 'react-native-animatable'; import CustomTabBar from "../Tabbar/CustomTabBar"; import {Collapsible} from "react-navigation-collapsible"; +import {StackNavigationProp} from "@react-navigation/stack"; type Props = { - navigation: { [key: string]: any }, + navigation: StackNavigationProp, fetchUrl: string, autoRefreshTime: number, refreshOnFocus: boolean, renderItem: (data: { [key: string]: any }) => React.Node, - createDataset: (data: { [key: string]: any }) => Array, + createDataset: (data: { [key: string]: any } | null, isLoading?: boolean) => Array, onScroll: (event: SyntheticEvent) => void, collapsibleStack: Collapsible, showError: boolean, itemHeight?: number, updateData?: number, - renderSectionHeader?: (data: { [key: string]: any }) => React.Node, + renderListHeaderComponent?: (data: { [key: string]: any } | null) => React.Node, + renderSectionHeader?: (data: { section: { [key: string]: any } }, isLoading?: boolean) => React.Node, stickyHeader?: boolean, } @@ -53,7 +55,6 @@ class WebSectionList extends React.PureComponent { showError: true, }; - scrollRef: { current: null | Animated.SectionList }; refreshInterval: IntervalID; lastRefresh: Date | null; @@ -69,31 +70,26 @@ class WebSectionList extends React.PureComponent { * Allows to detect when the screen is focused */ componentDidMount() { - const onScreenFocus = this.onScreenFocus.bind(this); - const onScreenBlur = this.onScreenBlur.bind(this); - this.props.navigation.addListener('focus', onScreenFocus); - this.props.navigation.addListener('blur', onScreenBlur); - this.scrollRef = React.createRef(); - this.onRefresh(); + this.props.navigation.addListener('focus', this.onScreenFocus); + this.props.navigation.addListener('blur', this.onScreenBlur); this.lastRefresh = null; + this.onRefresh(); } /** * Refreshes data when focusing the screen and setup a refresh interval if asked to */ - onScreenFocus() { + onScreenFocus = () => { if (this.props.refreshOnFocus && this.lastRefresh) this.onRefresh(); if (this.props.autoRefreshTime > 0) this.refreshInterval = setInterval(this.onRefresh, this.props.autoRefreshTime) - // if (this.scrollRef.current) // Reset scroll to top - // this.scrollRef.current.getNode().scrollToLocation({animated:false, itemIndex:0, sectionIndex:0}); } /** * Removes any interval on un-focus */ - onScreenBlur() { + onScreenBlur = () => { clearInterval(this.refreshInterval); } @@ -173,7 +169,7 @@ class WebSectionList extends React.PureComponent { duration={500} useNativeDriver > - {this.props.renderSectionHeader(data)} + {this.props.renderSectionHeader(data, this.state.refreshing)} ); } else @@ -205,16 +201,12 @@ class WebSectionList extends React.PureComponent { render() { let dataset = []; if (this.state.fetchedData != null || (this.state.fetchedData == null && !this.props.showError)) { - if (this.state.fetchedData == null) - dataset = this.props.createDataset({}); - else - dataset = this.props.createDataset(this.state.fetchedData); + dataset = this.props.createDataset(this.state.fetchedData, this.state.refreshing); } const {containerPaddingTop, scrollIndicatorInsetTop, onScrollWithListener} = this.props.collapsibleStack; return ( { renderItem={this.renderItem} stickySectionHeadersEnabled={this.props.stickyHeader} style={{minHeight: '100%'}} + ListHeaderComponent={this.props.renderListHeaderComponent != null + ? this.props.renderListHeaderComponent(this.state.fetchedData) + : null} ListEmptyComponent={this.state.refreshing ? : -}; - export type event = { id: number, title: string, @@ -78,12 +76,6 @@ export type event = { url: string, } -type listSection = { - title: string, - data: Array | Array, - id: string -}; - type Props = { navigation: StackNavigationProp, route: { params: any, ... }, @@ -203,84 +195,41 @@ class HomeScreen extends React.Component { hideDisconnectDialog = () => this.setState({dialogVisible: false}); + openScanner = () => this.props.navigation.navigate("scanner"); + /** * Creates the dataset to be used in the FlatList * * @param fetchedData + * @param isLoading * @return {*} */ - createDataset = (fetchedData: rawDashboard) => { + createDataset = (fetchedData: rawDashboard | null, isLoading: boolean) => { // fetchedData = DATA; - let dashboardData; - if (fetchedData.news_feed != null) - this.currentNewFeed = fetchedData.news_feed.data; - if (fetchedData.dashboard != null) - this.currentDashboard = fetchedData.dashboard; - - if (fetchedData.dashboard != null) - dashboardData = this.generateDashboardDataset(fetchedData.dashboard); + if (fetchedData != null) { + if (fetchedData.news_feed != null) + this.currentNewFeed = fetchedData.news_feed.data; + if (fetchedData.dashboard != null) + this.currentDashboard = fetchedData.dashboard; + } + if (this.currentNewFeed.length > 0) + return [ + { + title: i18n.t("screens.home.feedTitle"), + data: this.currentNewFeed, + id: SECTIONS_ID[1] + } + ]; else - dashboardData = this.generateDashboardDataset(null); - return [ - { - title: '', - data: dashboardData, - id: SECTIONS_ID[0] - }, - { - title: i18n.t("screens.home.feedTitle"), - data: this.currentNewFeed, - id: SECTIONS_ID[1] - } - ]; + return [ + { + title: isLoading ? i18n.t("screens.home.feedLoading") : i18n.t("screens.home.feedError"), + data: [], + id: SECTIONS_ID[1] + } + ]; }; - /** - * Generates the dataset associated to the dashboard to be displayed in the FlatList as a section - * - * @param dashboardData - * @return {Array} - */ - generateDashboardDataset(dashboardData: fullDashboard | null): Array { - return [ - {id: 'actions', content: []}, - { - id: 'top', - content: this.dashboardManager.getCurrentDashboard(), - }, - { - id: 'event', - content: dashboardData == null ? [] : dashboardData.today_events - }, - - ]; - } - - /** - * Gets a dashboard item - * - * @param item The item to display - * @return {*} - */ - getDashboardItem(item: dashboardItem) { - let content = item.content; - if (item.id === 'event') - return this.getDashboardEvent(content); - else if (item.id === 'top') - return this.getDashboardRow(content); - else - return this.getDashboardActions(); - } - - /** - * Gets a dashboard item with action buttons - * - * @returns {*} - */ - getDashboardActions() { - return ; - } - /** * Gets the time limit depending on the current day: * 17:30 for every day of the week except for thursday 11:30 @@ -427,22 +376,13 @@ class HomeScreen extends React.Component { } /** - * Gets a dashboard shortcut item + * Gets a dashboard item with action buttons * - * @param item * @returns {*} */ - dashboardRowRenderItem = ({item}: { item: DashboardItem }) => { - return ( - - ); - }; + getDashboardActions() { + return ; + } /** * Gets a dashboard item with a row of shortcut buttons. @@ -450,7 +390,7 @@ class HomeScreen extends React.Component { * @param content * @return {*} */ - getDashboardRow(content: Array) { + getDashboardRow(content: Array) { return ( //$FlowFixMe { />); } + /** + * Gets a dashboard shortcut item + * + * @param item + * @returns {*} + */ + dashboardRowRenderItem = ({item}: { item: ServiceItem }) => { + return ( + + ); + }; + /** * Gets a render item for the given feed object * @@ -491,28 +449,15 @@ class HomeScreen extends React.Component { * @param section The current section * @return {*} */ - getRenderItem = ({item, section}: { - item: { [key: string]: any }, - section: listSection - }) => { - if (section.id === SECTIONS_ID[0]) { - const data: dashboardItem = item; - return this.getDashboardItem(data); - } else { - const data: feedItem = item; - return this.getFeedItem(data); - } - }; - - openScanner = () => this.props.navigation.navigate("scanner"); + getRenderItem = ({item}: { item: feedItem, }) => this.getFeedItem(item); onScroll = (event: SyntheticEvent) => { if (this.fabRef.current != null) this.fabRef.current.onScroll(event); }; - renderSectionHeader = (data: { [key: string]: any }) => { - if (data.section.title !== "") + renderSectionHeader = (data: { section: { [key: string]: any } }, isLoading: boolean) => { + if (data.section.data.length > 0) return ( { ) else - return null; + return ( + + + {data.section.title} + + {isLoading + ? + : } + + + ); + } + + getListHeader = (fetchedData: rawDashboard) => { + let dashboard = null; + if (fetchedData != null) { + dashboard = fetchedData.dashboard; + } + + return ( + + {this.getDashboardActions()} + {this.getDashboardRow(this.dashboardManager.getCurrentDashboard())} + {this.getDashboardEvent( + dashboard == null + ? [] + : dashboard.today_events + )} + + ); } /** @@ -556,6 +553,7 @@ class HomeScreen extends React.Component { onScroll={this.onScroll} showError={false} renderSectionHeader={this.renderSectionHeader} + renderListHeaderComponent={this.getListHeader} />