/* * 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 { FlatList, Linking, Platform, Image, View, StyleSheet, } from 'react-native'; import i18n from 'i18n-js'; import { Avatar, Card, List } from 'react-native-paper'; import { StackNavigationProp } from '@react-navigation/stack'; import packageJson from '../../../package.json'; import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList'; import OptionsDialog from '../../components/Dialogs/OptionsDialog'; import type { OptionsDialogButtonType } from '../../components/Dialogs/OptionsDialog'; import GENERAL_STYLES from '../../constants/Styles'; import Urls from '../../constants/Urls'; const APP_LOGO = require('../../../assets/android.icon.round.png'); type ListItemType = { onPressCallback: () => void; icon: string; text: string; showChevron: boolean; }; type MemberItemType = { name: string; message: string; icon: string; trollLink?: string; linkedin?: string; mail?: string; }; type PropsType = { navigation: StackNavigationProp; }; type StateType = { dialogVisible: boolean; dialogTitle: string; dialogMessage: string; dialogButtons: Array; }; const styles = StyleSheet.create({ card: { marginBottom: 10, }, list: { padding: 5, }, }); /** * Opens a link in the device's browser * @param link The link to open */ function openWebLink(link: string) { Linking.openURL(link); } /** * Class defining an about screen. This screen shows the user information about the app and it's author. */ class AboutScreen extends React.Component { /** * Object containing data relative to major contributors */ majorContributors: Array = [ { name: 'Arnaud Vergnet', message: i18n.t('screens.about.user.arnaud'), icon: 'crown', trollLink: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', linkedin: 'https://www.linkedin.com/in/arnaud-vergnet-434ba5179/', mail: 'mailto:vergnet@etud.insa-toulouse.fr?' + 'subject=' + 'Application Amicale INSA Toulouse' + '&body=' + 'Coucou !\n\n', }, { name: 'Jean-Yves Saint-Loubert', message: i18n.t('screens.about.user.docjyj'), icon: 'xml', mail: 'mailto:saint-lo@etud.insa-toulouse.fr?' + 'subject=' + 'Application Amicale INSA Toulouse' + '&body=' + 'Coucou !\n\n', }, { name: 'Yohan Simard', message: i18n.t('screens.about.user.yohan'), icon: 'xml', linkedin: 'https://www.linkedin.com/in/yohan-simard', mail: 'mailto:ysimard@etud.insa-toulouse.fr?' + 'subject=' + 'Application Amicale INSA Toulouse' + '&body=' + 'Coucou !\n\n', }, ]; /** * Object containing data relative to users who helped during development */ helpfulUsers: Array = [ { name: 'Béranger Quintana Y Arciosana', message: i18n.t('screens.about.user.beranger'), icon: 'account-heart', }, { name: 'Céline Tassin', message: i18n.t('screens.about.user.celine'), icon: 'brush', }, { name: 'Damien Molina', message: i18n.t('screens.about.user.damien'), icon: 'web', }, { name: 'Titouan Labourdette', message: i18n.t('screens.about.user.titouan'), icon: 'shield-bug', }, { name: 'Théo Tami', message: i18n.t('screens.about.user.theo'), icon: 'food-apple', }, ]; /** * Data to be displayed in the app card */ appData: Array = [ { onPressCallback: () => { openWebLink( Platform.OS === 'ios' ? Urls.about.appstore : Urls.about.playstore ); }, icon: Platform.OS === 'ios' ? 'apple' : 'google-play', text: Platform.OS === 'ios' ? i18n.t('screens.about.appstore') : i18n.t('screens.about.playstore'), showChevron: true, }, { onPressCallback: () => { const { navigation } = this.props; navigation.navigate('feedback'); }, icon: 'bug', text: i18n.t('screens.feedback.homeButtonTitle'), showChevron: true, }, { onPressCallback: () => { openWebLink(Urls.about.git); }, icon: 'git', text: 'Git', showChevron: true, }, { onPressCallback: () => { openWebLink(Urls.about.changelog); }, icon: 'refresh', text: i18n.t('screens.about.changelog'), showChevron: true, }, { onPressCallback: () => { openWebLink(Urls.about.license); }, icon: 'file-document', text: i18n.t('screens.about.license'), showChevron: true, }, ]; /** * Data to be displayed in the team card */ teamData: Array; /** * Data to be displayed in the thanks card */ thanksData: Array; /** * Data to be displayed in the technologies card */ technoData = [ { onPressCallback: () => { openWebLink(Urls.about.react); }, icon: 'react', text: i18n.t('screens.about.reactNative'), showChevron: true, }, { onPressCallback: () => { const { navigation } = this.props; navigation.navigate('dependencies'); }, icon: 'developer-board', text: i18n.t('screens.about.libs'), showChevron: true, }, ]; /** * Order of information cards */ dataOrder = [ { id: 'app', }, { id: 'team', }, { id: 'thanks', }, { id: 'techno', }, ]; constructor(props: PropsType) { super(props); this.state = { dialogVisible: false, dialogTitle: '', dialogMessage: '', dialogButtons: [], }; this.teamData = [ ...this.getMemberData(this.majorContributors), { onPressCallback: () => { const { navigation } = this.props; navigation.navigate('feedback'); }, icon: 'hand-pointing-right', text: i18n.t('screens.about.user.you'), showChevron: true, }, ]; this.thanksData = this.getMemberData(this.helpfulUsers); } getMemberData(data: Array): Array { const final: Array = []; data.forEach((item) => { final.push({ onPressCallback: () => { this.onContributorListItemPress(item); }, icon: item.icon, text: item.name, showChevron: false, }); }); return final; } /** * Callback used when clicking a member in the list * It opens a dialog to show detailed information this member * * @param user The member to show information for */ onContributorListItemPress(user: MemberItemType) { const dialogBtn: Array = [ { title: 'OK', onPress: this.onDialogDismiss, }, ]; const { linkedin, trollLink, mail } = user; if (linkedin != null) { dialogBtn.push({ title: '', icon: 'linkedin', onPress: () => { openWebLink(linkedin); }, }); } if (mail) { dialogBtn.push({ title: '', icon: 'email-edit', onPress: () => { openWebLink(mail); }, }); } if (trollLink) { dialogBtn.push({ title: 'Coucou', onPress: () => { openWebLink(trollLink); }, }); } this.setState({ dialogVisible: true, dialogTitle: user.name, dialogMessage: user.message, dialogButtons: dialogBtn, }); } /** * Gets the app card showing information and links about the app. * * @return {*} */ getAppCard() { return ( ( )} /> ); } /** * Gets the team card showing information and links about the team * * @return {*} */ getTeamCard() { return ( ( )} /> ); } /** * Get the thank you card showing support information and links * * @return {*} */ getThanksCard() { return ( ( )} /> ); } /** * Gets the techno card showing information and links about the technologies used in the app * * @return {*} */ getTechnoCard() { return ( ( )} /> ); } /** * Gets a chevron icon * * @param props * @return {*} */ static getChevronIcon(props: { color: string; style?: { marginRight: number; marginVertical?: number; }; }) { return ( ); } /** * Gets a custom list item icon * * @param item The item to show the icon for * @param props * @return {*} */ static getItemIcon( item: ListItemType, props: { color: string; style?: { marginRight: number; marginVertical?: number; }; } ) { return ( ); } /** * Gets a clickable card item to be rendered inside a card. * * @returns {*} */ getCardItem = ({ item }: { item: ListItemType }) => { const getItemIcon = (props: { color: string; style?: { marginRight: number; marginVertical?: number; }; }) => AboutScreen.getItemIcon(item, props); if (item.showChevron) { return ( ); } return ( ); }; /** * Gets a card, depending on the given item's id * * @param item The item to show * @return {*} */ getMainCard = ({ item }: { item: { id: string } }) => { switch (item.id) { case 'app': return this.getAppCard(); case 'team': return this.getTeamCard(); case 'thanks': return this.getThanksCard(); case 'techno': return this.getTechnoCard(); default: return null; } }; onDialogDismiss = () => { this.setState({ dialogVisible: false }); }; /** * Extracts a key from the given item * * @param item The item to extract the key from * @return {string} The extracted key */ keyExtractor = (item: ListItemType): string => item.icon; render() { const { state } = this; return ( ); } } export default AboutScreen;