diff --git a/src/components/Home/ActionsDashboardItem.js b/src/components/Home/ActionsDashboardItem.js deleted file mode 100644 index 7c68d8f..0000000 --- a/src/components/Home/ActionsDashboardItem.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Arnaud Vergnet. - * - * This file is part of Campus INSAT. - * - * Campus INSAT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Campus INSAT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Campus INSAT. If not, see . - */ - -// @flow - -import * as React from 'react'; -import {List, withTheme} from 'react-native-paper'; -import {View} from 'react-native'; -import i18n from 'i18n-js'; -import {StackNavigationProp} from '@react-navigation/stack'; -import type {CustomThemeType} from '../../managers/ThemeManager'; -import type {ListIconPropsType} from '../../constants/PaperStyles'; - -type PropsType = { - navigation: StackNavigationProp, - theme: CustomThemeType, -}; - -class ActionsDashBoardItem extends React.Component { - shouldComponentUpdate(nextProps: PropsType): boolean { - const {props} = this; - return nextProps.theme.dark !== props.theme.dark; - } - - render(): React.Node { - const {navigation} = this.props; - return ( - - ( - - )} - right={(props: ListIconPropsType): React.Node => ( - - )} - onPress={(): void => navigation.navigate('feedback')} - style={{ - paddingTop: 0, - paddingBottom: 0, - marginLeft: 10, - marginRight: 10, - }} - /> - - ); - } -} - -export default withTheme(ActionsDashBoardItem); diff --git a/src/components/Home/ActionsDashboardItem.tsx b/src/components/Home/ActionsDashboardItem.tsx new file mode 100644 index 0000000..982ec11 --- /dev/null +++ b/src/components/Home/ActionsDashboardItem.tsx @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 - 2020 Arnaud Vergnet. + * + * This file is part of Campus INSAT. + * + * Campus INSAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Campus INSAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Campus INSAT. If not, see . + */ + +import * as React from 'react'; +import {List} from 'react-native-paper'; +import {View} from 'react-native'; +import i18n from 'i18n-js'; +import {useNavigation} from '@react-navigation/native'; + +function ActionsDashBoardItem() { + const navigation = useNavigation(); + return ( + + ( + + )} + right={(props) => ( + + )} + onPress={(): void => navigation.navigate('feedback')} + style={{ + paddingTop: 0, + paddingBottom: 0, + marginLeft: 10, + marginRight: 10, + }} + /> + + ); +} + +export default ActionsDashBoardItem; diff --git a/src/components/Home/EventDashboardItem.js b/src/components/Home/EventDashboardItem.js deleted file mode 100644 index 4a8ce0d..0000000 --- a/src/components/Home/EventDashboardItem.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Arnaud Vergnet. - * - * This file is part of Campus INSAT. - * - * Campus INSAT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Campus INSAT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Campus INSAT. If not, see . - */ - -// @flow - -import * as React from 'react'; -import { - Avatar, - Card, - Text, - TouchableRipple, - withTheme, -} from 'react-native-paper'; -import {StyleSheet, View} from 'react-native'; -import i18n from 'i18n-js'; -import type {CustomThemeType} from '../../managers/ThemeManager'; -import type {CardTitleIconPropsType} from '../../constants/PaperStyles'; - -type PropsType = { - eventNumber: number, - clickAction: () => void, - theme: CustomThemeType, - children?: React.Node, -}; - -const styles = StyleSheet.create({ - card: { - width: 'auto', - marginLeft: 10, - marginRight: 10, - marginTop: 10, - overflow: 'hidden', - }, - avatar: { - backgroundColor: 'transparent', - }, -}); - -/** - * Component used to display a dashboard item containing a preview event - */ -class EventDashBoardItem extends React.Component { - static defaultProps = { - children: null, - }; - - shouldComponentUpdate(nextProps: PropsType): boolean { - const {props} = this; - return ( - nextProps.theme.dark !== props.theme.dark || - nextProps.eventNumber !== props.eventNumber - ); - } - - render(): React.Node { - const {props} = this; - const {colors} = props.theme; - const isAvailable = props.eventNumber > 0; - const iconColor = isAvailable ? colors.planningColor : colors.textDisabled; - const textColor = isAvailable ? colors.text : colors.textDisabled; - let subtitle; - if (isAvailable) { - subtitle = ( - - {props.eventNumber} - - {props.eventNumber > 1 - ? i18n.t('screens.home.dashboard.todayEventsSubtitlePlural') - : i18n.t('screens.home.dashboard.todayEventsSubtitle')} - - - ); - } else subtitle = i18n.t('screens.home.dashboard.todayEventsSubtitleNA'); - return ( - - - - ( - - )} - /> - {props.children} - - - - ); - } -} - -export default withTheme(EventDashBoardItem); diff --git a/src/components/Home/EventDashboardItem.tsx b/src/components/Home/EventDashboardItem.tsx new file mode 100644 index 0000000..2936fd2 --- /dev/null +++ b/src/components/Home/EventDashboardItem.tsx @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019 - 2020 Arnaud Vergnet. + * + * This file is part of Campus INSAT. + * + * Campus INSAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Campus INSAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Campus INSAT. If not, see . + */ + +import * as React from 'react'; +import { + Avatar, + Card, + Text, + TouchableRipple, + useTheme, +} from 'react-native-paper'; +import {StyleSheet, View} from 'react-native'; +import i18n from 'i18n-js'; + +type PropsType = { + eventNumber: number; + clickAction: () => void; + children?: React.ReactNode; +}; + +const styles = StyleSheet.create({ + card: { + width: 'auto', + marginLeft: 10, + marginRight: 10, + marginTop: 10, + overflow: 'hidden', + }, + avatar: { + backgroundColor: 'transparent', + }, +}); + +/** + * Component used to display a dashboard item containing a preview event + */ +function EventDashBoardItem(props: PropsType) { + const theme = useTheme(); + const isAvailable = props.eventNumber > 0; + const iconColor = isAvailable + ? theme.colors.planningColor + : theme.colors.textDisabled; + const textColor = isAvailable ? theme.colors.text : theme.colors.textDisabled; + let subtitle; + if (isAvailable) { + subtitle = ( + + {props.eventNumber} + + {props.eventNumber > 1 + ? i18n.t('screens.home.dashboard.todayEventsSubtitlePlural') + : i18n.t('screens.home.dashboard.todayEventsSubtitle')} + + + ); + } else { + subtitle = i18n.t('screens.home.dashboard.todayEventsSubtitleNA'); + } + return ( + + + + ( + + )} + /> + {props.children} + + + + ); +} + +const areEqual = (prevProps: PropsType, nextProps: PropsType): boolean => { + return nextProps.eventNumber !== prevProps.eventNumber; +}; + +export default React.memo(EventDashBoardItem, areEqual); diff --git a/src/components/Home/FeedItem.js b/src/components/Home/FeedItem.js deleted file mode 100644 index 2bdd9a1..0000000 --- a/src/components/Home/FeedItem.js +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Arnaud Vergnet. - * - * This file is part of Campus INSAT. - * - * Campus INSAT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Campus INSAT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Campus INSAT. If not, see . - */ - -// @flow - -import * as React from 'react'; -import {Button, Card, Text, TouchableRipple} from 'react-native-paper'; -import {Image, View} from 'react-native'; -import Autolink from 'react-native-autolink'; -import i18n from 'i18n-js'; -import {StackNavigationProp} from '@react-navigation/stack'; -import type {FeedItemType} from '../../screens/Home/HomeScreen'; -import NewsSourcesConstants from '../../constants/NewsSourcesConstants'; -import type {NewsSourceType} from '../../constants/NewsSourcesConstants'; -import ImageGalleryButton from '../Media/ImageGalleryButton'; - -type PropsType = { - navigation: StackNavigationProp, - item: FeedItemType, - height: number, -}; - -/** - * Component used to display a feed item - */ -class FeedItem extends React.Component { - /** - * Converts a dateString using Unix Timestamp to a formatted date - * - * @param dateString {string} The Unix Timestamp representation of a date - * @return {string} The formatted output date - */ - static getFormattedDate(dateString: number): string { - const date = new Date(dateString * 1000); - return date.toLocaleString(); - } - - shouldComponentUpdate(): boolean { - return false; - } - - onPress = () => { - const {item, navigation} = this.props; - navigation.navigate('feed-information', { - data: item, - date: FeedItem.getFormattedDate(item.time), - }); - }; - - render(): React.Node { - const {item, height, navigation} = this.props; - const image = item.image !== '' && item.image != null ? item.image : null; - const pageSource: NewsSourceType = NewsSourcesConstants[item.page_id]; - const cardMargin = 10; - const cardHeight = height - 2 * cardMargin; - const imageSize = 250; - const titleHeight = 80; - const actionsHeight = 60; - const textHeight = - image != null - ? cardHeight - titleHeight - actionsHeight - imageSize - : cardHeight - titleHeight - actionsHeight; - return ( - - - - ( - - )} - style={{height: titleHeight}} - /> - {image != null ? ( - - ) : null} - - {item.message !== undefined ? ( - - ) : null} - - - - - - - - ); - } -} - -export default FeedItem; diff --git a/src/components/Home/FeedItem.tsx b/src/components/Home/FeedItem.tsx new file mode 100644 index 0000000..f9627ff --- /dev/null +++ b/src/components/Home/FeedItem.tsx @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2019 - 2020 Arnaud Vergnet. + * + * This file is part of Campus INSAT. + * + * Campus INSAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Campus INSAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Campus INSAT. If not, see . + */ + +import * as React from 'react'; +import {Button, Card, Text, TouchableRipple} from 'react-native-paper'; +import {Image, View} from 'react-native'; +import Autolink from 'react-native-autolink'; +import i18n from 'i18n-js'; +import type {FeedItemType} from '../../screens/Home/HomeScreen'; +import NewsSourcesConstants, { + AvailablePages, +} from '../../constants/NewsSourcesConstants'; +import type {NewsSourceType} from '../../constants/NewsSourcesConstants'; +import ImageGalleryButton from '../Media/ImageGalleryButton'; +import {useNavigation} from '@react-navigation/native'; + +type PropsType = { + item: FeedItemType; + height: number; +}; + +/** + * Converts a dateString using Unix Timestamp to a formatted date + * + * @param dateString {string} The Unix Timestamp representation of a date + * @return {string} The formatted output date + */ +function getFormattedDate(dateString: number): string { + const date = new Date(dateString * 1000); + return date.toLocaleString(); +} + +/** + * Component used to display a feed item + */ +function FeedItem(props: PropsType) { + const navigation = useNavigation(); + const onPress = () => { + navigation.navigate('feed-information', { + data: item, + date: getFormattedDate(props.item.time), + }); + }; + + const {item, height} = props; + const image = item.image !== '' && item.image != null ? item.image : null; + const pageSource: NewsSourceType = + NewsSourcesConstants[item.page_id as AvailablePages]; + const cardMargin = 10; + const cardHeight = height - 2 * cardMargin; + const imageSize = 250; + const titleHeight = 80; + const actionsHeight = 60; + const textHeight = + image != null + ? cardHeight - titleHeight - actionsHeight - imageSize + : cardHeight - titleHeight - actionsHeight; + return ( + + + + ( + + )} + style={{height: titleHeight}} + /> + {image != null ? ( + + ) : null} + + {item.message !== undefined ? ( + + text={item.message} + hashtag="facebook" + component={Text} + style={{height: textHeight}} + /> + ) : null} + + + + + + + + ); +} + +export default React.memo(FeedItem, () => true); diff --git a/src/components/Home/PreviewEventDashboardItem.js b/src/components/Home/PreviewEventDashboardItem.js deleted file mode 100644 index e96cd51..0000000 --- a/src/components/Home/PreviewEventDashboardItem.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Arnaud Vergnet. - * - * This file is part of Campus INSAT. - * - * Campus INSAT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Campus INSAT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Campus INSAT. If not, see . - */ - -// @flow - -import * as React from 'react'; -import {StyleSheet, View} from 'react-native'; -import i18n from 'i18n-js'; -import {Avatar, Button, Card, TouchableRipple} from 'react-native-paper'; -import {getTimeOnlyString, isDescriptionEmpty} from '../../utils/Planning'; -import CustomHTML from '../Overrides/CustomHTML'; -import type {PlanningEventType} from '../../utils/Planning'; - -type PropsType = { - event?: PlanningEventType | null, - clickAction: () => void, -}; - -const styles = StyleSheet.create({ - card: { - marginBottom: 10, - }, - content: { - maxHeight: 150, - overflow: 'hidden', - }, - actions: { - marginLeft: 'auto', - marginTop: 'auto', - flexDirection: 'row', - }, - avatar: { - backgroundColor: 'transparent', - }, -}); - -/** - * Component used to display an event preview if an event is available - */ -// eslint-disable-next-line react/prefer-stateless-function -class PreviewEventDashboardItem extends React.Component { - static defaultProps = { - event: null, - }; - - render(): React.Node { - const {props} = this; - const {event} = props; - const isEmpty = - event == null ? true : isDescriptionEmpty(event.description); - - if (event != null) { - const hasImage = event.logo !== '' && event.logo != null; - const getImage = (): React.Node => ( - - ); - return ( - - - - {hasImage ? ( - - ) : ( - - )} - {!isEmpty ? ( - - - - ) : null} - - - - - - - - ); - } - return null; - } -} - -export default PreviewEventDashboardItem; diff --git a/src/components/Home/PreviewEventDashboardItem.tsx b/src/components/Home/PreviewEventDashboardItem.tsx new file mode 100644 index 0000000..ae79354 --- /dev/null +++ b/src/components/Home/PreviewEventDashboardItem.tsx @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 - 2020 Arnaud Vergnet. + * + * This file is part of Campus INSAT. + * + * Campus INSAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Campus INSAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Campus INSAT. If not, see . + */ + +import * as React from 'react'; +import {StyleSheet, View} from 'react-native'; +import i18n from 'i18n-js'; +import {Avatar, Button, Card, TouchableRipple} from 'react-native-paper'; +import {getTimeOnlyString, isDescriptionEmpty} from '../../utils/Planning'; +import CustomHTML from '../Overrides/CustomHTML'; +import type {PlanningEventType} from '../../utils/Planning'; + +type PropsType = { + event?: PlanningEventType | null; + clickAction: () => void; +}; + +const styles = StyleSheet.create({ + card: { + marginBottom: 10, + }, + content: { + maxHeight: 150, + overflow: 'hidden', + }, + actions: { + marginLeft: 'auto', + marginTop: 'auto', + flexDirection: 'row', + }, + avatar: { + backgroundColor: 'transparent', + }, +}); + +/** + * Component used to display an event preview if an event is available + */ +function PreviewEventDashboardItem(props: PropsType) { + const {event} = props; + const isEmpty = event == null ? true : isDescriptionEmpty(event.description); + + if (event != null) { + const logo = event.logo; + const getImage = logo + ? () => ( + + ) + : () => null; + return ( + + + + + {!isEmpty ? ( + + + + ) : null} + + + + + + + + ); + } + return null; +} + +export default PreviewEventDashboardItem; diff --git a/src/components/Home/SmallDashboardItem.js b/src/components/Home/SmallDashboardItem.js deleted file mode 100644 index 26cf6bc..0000000 --- a/src/components/Home/SmallDashboardItem.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Arnaud Vergnet. - * - * This file is part of Campus INSAT. - * - * Campus INSAT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Campus INSAT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Campus INSAT. If not, see . - */ - -// @flow - -import * as React from 'react'; -import {Badge, TouchableRipple, withTheme} from 'react-native-paper'; -import {Dimensions, Image, View} from 'react-native'; -import * as Animatable from 'react-native-animatable'; -import type {CustomThemeType} from '../../managers/ThemeManager'; - -type PropsType = { - image: string | null, - onPress: () => void | null, - badgeCount: number | null, - theme: CustomThemeType, -}; - -/** - * Component used to render a small dashboard item - */ -class SmallDashboardItem extends React.Component { - itemSize: number; - - constructor(props: PropsType) { - super(props); - this.itemSize = Dimensions.get('window').width / 8; - } - - shouldComponentUpdate(nextProps: PropsType): boolean { - const {props} = this; - return ( - nextProps.theme.dark !== props.theme.dark || - nextProps.badgeCount !== props.badgeCount - ); - } - - render(): React.Node { - const {props} = this; - return ( - - - - {props.badgeCount != null && props.badgeCount > 0 ? ( - - - {props.badgeCount} - - - ) : null} - - - ); - } -} - -export default withTheme(SmallDashboardItem); diff --git a/src/components/Home/SmallDashboardItem.tsx b/src/components/Home/SmallDashboardItem.tsx new file mode 100644 index 0000000..7052b1a --- /dev/null +++ b/src/components/Home/SmallDashboardItem.tsx @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019 - 2020 Arnaud Vergnet. + * + * This file is part of Campus INSAT. + * + * Campus INSAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Campus INSAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Campus INSAT. If not, see . + */ + +import * as React from 'react'; +import {Badge, TouchableRipple, useTheme} from 'react-native-paper'; +import {Dimensions, Image, View} from 'react-native'; +import * as Animatable from 'react-native-animatable'; + +type PropsType = { + image: string | null; + onPress: () => void | null; + badgeCount: number | null; +}; + +/** + * Component used to render a small dashboard item + */ +function SmallDashboardItem(props: PropsType) { + const itemSize = Dimensions.get('window').width / 8; + const theme = useTheme(); + const {image} = props; + return ( + + + {image ? ( + + ) : null} + {props.badgeCount != null && props.badgeCount > 0 ? ( + + + {props.badgeCount} + + + ) : null} + + + ); +} + +const areEqual = (prevProps: PropsType, nextProps: PropsType): boolean => { + return nextProps.badgeCount !== prevProps.badgeCount; +}; + +export default React.memo(SmallDashboardItem, areEqual); diff --git a/src/constants/NewsSourcesConstants.ts b/src/constants/NewsSourcesConstants.ts index d9aba6c..1e5ecd3 100644 --- a/src/constants/NewsSourcesConstants.ts +++ b/src/constants/NewsSourcesConstants.ts @@ -27,6 +27,8 @@ export type NewsSourceType = { name: string; }; +export type AvailablePages = 'amicale.deseleves' | 'campus.insat'; + export default { 'amicale.deseleves': { icon: ICON_AMICALE,