application-amicale/screens/About/AboutScreen.js

477 lines
14 KiB
JavaScript
Raw Normal View History

// @flow
import * as React from 'react';
import {FlatList, Linking, Platform, View} from 'react-native';
2019-06-25 22:20:24 +02:00
import i18n from "i18n-js";
2019-06-27 11:08:56 +02:00
import appJson from '../../app';
2020-03-30 15:28:08 +02:00
import AsyncStorageManager from "../../managers/AsyncStorageManager";
2020-04-02 10:07:20 +02:00
import CustomModal from "../../components/Custom/CustomModal";
import {Avatar, Button, Card, List, Text, Title, withTheme} from 'react-native-paper';
2019-06-25 22:20:24 +02:00
const links = {
2019-08-31 10:55:56 +02:00
appstore: 'https://apps.apple.com/us/app/campus-amicale-insat/id1477722148',
2019-08-24 19:17:21 +02:00
playstore: 'https://play.google.com/store/apps/details?id=fr.amicaleinsat.application',
git: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/README.md',
2019-09-17 11:51:26 +02:00
bugsMail: 'mailto:vergnet@etud.insa-toulouse.fr?' +
'subject=' +
'[BUG] Application Amicale INSA Toulouse' +
'&body=' +
'Coucou Arnaud ça bug c\'est nul,\n\n' +
'Informations sur ton système si tu sais (iOS ou Android, modèle du tel, version):\n\n\n' +
'Nature du problème :\n\n\n' +
'Étapes pour reproduire ce pb :\n\n\n\n' +
'Stp corrige le pb, bien cordialement.',
bugsGit: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues',
changelog: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/Changelog.md',
license: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/LICENSE',
2019-11-16 12:55:47 +01:00
authorMail: "mailto:vergnet@etud.insa-toulouse.fr?" +
2019-09-17 11:51:26 +02:00
"subject=" +
"Application Amicale INSA Toulouse" +
"&body=" +
"Coucou !\n\n",
2019-11-16 12:55:47 +01:00
authorLinkedin: 'https://www.linkedin.com/in/arnaud-vergnet-434ba5179/',
2019-11-16 13:19:28 +01:00
yohanMail: "mailto:ysimard@etud.insa-toulouse.fr?" +
2019-11-16 12:55:47 +01:00
"subject=" +
"Application Amicale INSA Toulouse" +
"&body=" +
"Coucou !\n\n",
yohanLinkedin: 'https://www.linkedin.com/in/yohan-simard',
2019-06-25 22:20:24 +02:00
react: 'https://facebook.github.io/react-native/',
};
type Props = {
navigation: Object,
};
type State = {
isDebugUnlocked: boolean,
};
2019-06-29 15:43:57 +02:00
/**
* Opens a link in the device's browser
* @param link The link to open
*/
2019-06-28 11:35:15 +02:00
function openWebLink(link) {
Linking.openURL(link).catch((err) => console.error('Error opening link', err));
}
2019-06-25 22:20:24 +02:00
2019-06-29 15:43:57 +02:00
/**
* Class defining an about screen. This screen shows the user information about the app and it's author.
*/
class AboutScreen extends React.Component<Props, State> {
debugTapCounter = 0;
modalRef: Object;
state = {
isDebugUnlocked: AsyncStorageManager.getInstance().preferences.debugUnlocked.current === '1'
};
2019-06-29 15:43:57 +02:00
/**
* Data to be displayed in the app card
*/
appData: Array<Object> = [
2019-06-28 11:35:15 +02:00
{
onPressCallback: () => openWebLink(Platform.OS === "ios" ? links.appstore : links.playstore),
icon: Platform.OS === "ios" ? 'apple' : 'google-play',
text: Platform.OS === "ios" ? i18n.t('aboutScreen.appstore') : i18n.t('aboutScreen.playstore'),
showChevron: true
},
{
2019-09-17 11:51:26 +02:00
onPressCallback: () => this.openBugReportModal(),
icon: 'bug',
text: i18n.t('aboutScreen.bugs'),
2019-08-05 15:10:20 +02:00
showChevron: true
},
{
onPressCallback: () => openWebLink(links.git),
2019-06-28 11:35:15 +02:00
icon: 'git',
2019-08-05 15:10:20 +02:00
text: 'Git',
2019-06-28 11:35:15 +02:00
showChevron: true
},
{
onPressCallback: () => openWebLink(links.changelog),
icon: 'refresh',
text: i18n.t('aboutScreen.changelog'),
showChevron: true
},
{
onPressCallback: () => openWebLink(links.license),
icon: 'file-document',
text: i18n.t('aboutScreen.license'),
showChevron: true
},
{
onPressCallback: () => this.props.navigation.navigate('DebugScreen'),
icon: 'bug-check',
text: i18n.t('aboutScreen.debug'),
showChevron: true,
showOnlyInDebug: true
},
2019-06-28 11:35:15 +02:00
];
2019-06-29 15:43:57 +02:00
/**
* Data to be displayed in the author card
*/
authorData: Array<Object> = [
2019-06-28 11:35:15 +02:00
{
onPressCallback: () => this.tryUnlockDebugMode(),
2019-06-28 11:35:15 +02:00
icon: 'account-circle',
text: 'Arnaud VERGNET',
showChevron: false
},
{
2019-11-16 12:55:47 +01:00
onPressCallback: () => openWebLink(links.authorMail),
2019-06-28 11:35:15 +02:00
icon: 'email',
2019-11-16 12:55:47 +01:00
text: i18n.t('aboutScreen.authorMail'),
2019-06-28 11:35:15 +02:00
showChevron: true
},
{
2019-11-16 12:55:47 +01:00
onPressCallback: () => openWebLink(links.authorLinkedin),
2019-06-28 11:35:15 +02:00
icon: 'linkedin',
text: 'Linkedin',
showChevron: true
},
2019-11-16 12:55:47 +01:00
];
/**
* Data to be displayed in the additional developer card
*/
additionalDevData: Array<Object> = [
{
onPressCallback: () => console.log('Meme this'),
icon: 'account',
text: 'Yohan SIMARD',
showChevron: false
},
{
onPressCallback: () => openWebLink(links.yohanMail),
icon: 'email',
text: i18n.t('aboutScreen.authorMail'),
showChevron: true
},
2019-06-28 11:35:15 +02:00
{
2019-11-16 12:55:47 +01:00
onPressCallback: () => openWebLink(links.yohanLinkedin),
icon: 'linkedin',
text: 'Linkedin',
2019-06-28 11:35:15 +02:00
showChevron: true
},
];
2019-06-29 15:43:57 +02:00
/**
* Data to be displayed in the technologies card
*/
technoData: Array<Object> = [
2019-06-28 11:35:15 +02:00
{
onPressCallback: () => openWebLink(links.react),
icon: 'react',
text: i18n.t('aboutScreen.reactNative'),
showChevron: true
2019-06-28 11:35:15 +02:00
},
{
2020-03-06 09:12:56 +01:00
onPressCallback: () => this.props.navigation.navigate('AboutDependenciesScreen'),
2019-06-28 11:35:15 +02:00
icon: 'developer-board',
text: i18n.t('aboutScreen.libs'),
showChevron: true
},
];
/**
* Order of information cards
*/
dataOrder: Array<Object> = [
{
id: 'app',
},
{
id: 'team',
},
{
id: 'techno',
},
];
getCardItem: Function;
getMainCard: Function;
onModalRef: Function;
2020-03-10 11:33:22 +01:00
onPressMail: Function;
onPressGit: Function;
2020-03-10 11:33:22 +01:00
colors: Object;
constructor(props) {
2020-01-31 16:51:43 +01:00
super(props);
this.getCardItem = this.getCardItem.bind(this);
this.getMainCard = this.getMainCard.bind(this);
this.onModalRef = this.onModalRef.bind(this);
2020-03-10 11:33:22 +01:00
this.onPressMail = openWebLink.bind(this, links.bugsMail);
this.onPressGit = openWebLink.bind(this, links.bugsGit);
this.colors = props.theme.colors;
2020-01-31 16:51:43 +01:00
}
/**
* Gets the app icon
* @param props
* @return {*}
*/
2020-03-10 11:33:22 +01:00
getAppIcon(props) {
return (
<Avatar.Image
{...props}
source={require('../../assets/android.icon.png')}
style={{backgroundColor: 'transparent'}}
/>
);
}
/**
* Extracts a key from the given item
*
* @param item The item to extract the key from
* @return {string} The extracted key
*/
keyExtractor(item: Object): string {
2020-03-10 11:33:22 +01:00
return item.icon;
}
/**
* Gets the app card showing information and links about the app.
*
* @return {*}
*/
getAppCard() {
return (
<Card style={{marginBottom: 10}}>
<Card.Title
title={appJson.expo.name}
subtitle={appJson.expo.version}
2020-03-10 11:33:22 +01:00
left={this.getAppIcon}/>
<Card.Content>
<FlatList
data={this.appData}
2020-03-10 11:33:22 +01:00
keyExtractor={this.keyExtractor}
renderItem={this.getCardItem}
/>
</Card.Content>
</Card>
);
}
/**
* Gets the team card showing information and links about the team
*
* @return {*}
*/
getTeamCard() {
return (
<Card style={{marginBottom: 10}}>
<Card.Title
title={i18n.t('aboutScreen.team')}
left={(props) => <Avatar.Icon {...props} icon={'account-multiple'}/>}/>
<Card.Content>
<Title>{i18n.t('aboutScreen.author')}</Title>
<FlatList
data={this.authorData}
2020-03-10 11:33:22 +01:00
keyExtractor={this.keyExtractor}
listKey={"1"}
renderItem={this.getCardItem}
/>
<Title>{i18n.t('aboutScreen.additionalDev')}</Title>
<FlatList
data={this.additionalDevData}
2020-03-10 11:33:22 +01:00
keyExtractor={this.keyExtractor}
listKey={"2"}
renderItem={this.getCardItem}
/>
</Card.Content>
</Card>
);
}
/**
* Gets the techno card showing information and links about the technologies used in the app
*
* @return {*}
*/
getTechnoCard() {
return (
<Card style={{marginBottom: 10}}>
<Card.Content>
<Title>{i18n.t('aboutScreen.technologies')}</Title>
<FlatList
data={this.technoData}
2020-03-10 11:33:22 +01:00
keyExtractor={this.keyExtractor}
renderItem={this.getCardItem}
/>
</Card.Content>
</Card>
);
}
/**
* Gets a chevron icon
*
* @param props
* @return {*}
*/
2020-03-10 11:33:22 +01:00
getChevronIcon(props: Object) {
return (
<List.Icon {...props} icon={'chevron-right'}/>
);
}
/**
* Gets a custom list item icon
*
* @param item The item to show the icon for
* @param props
* @return {*}
*/
2020-03-10 11:33:22 +01:00
getItemIcon(item: Object, props: Object) {
return (
<List.Icon {...props} icon={item.icon}/>
);
}
2019-06-29 15:43:57 +02:00
/**
* Get a clickable card item to be rendered inside a card.
*
* @returns {*}
2019-06-29 15:43:57 +02:00
*/
getCardItem({item}: Object) {
let shouldShow = item === undefined
|| !item.showOnlyInDebug
|| (item.showOnlyInDebug && this.state.isDebugUnlocked);
2020-03-10 11:33:22 +01:00
const getItemIcon = this.getItemIcon.bind(this, item);
if (shouldShow) {
if (item.showChevron) {
return (
<List.Item
title={item.text}
2020-03-10 11:33:22 +01:00
left={getItemIcon}
right={this.getChevronIcon}
onPress={item.onPressCallback}
/>
);
} else {
return (
<List.Item
title={item.text}
2020-03-10 11:33:22 +01:00
left={getItemIcon}
onPress={item.onPressCallback}
/>
);
}
2020-03-10 11:33:22 +01:00
} else
return null;
}
/**
* Tries to unlock debug mode
*/
tryUnlockDebugMode() {
this.debugTapCounter = this.debugTapCounter + 1;
if (this.debugTapCounter >= 4) {
this.unlockDebugMode();
}
}
/**
* Unlocks debug mode
*/
unlockDebugMode() {
this.setState({isDebugUnlocked: true});
let key = AsyncStorageManager.getInstance().preferences.debugUnlocked.key;
AsyncStorageManager.getInstance().savePref(key, '1');
2019-06-25 22:20:24 +02:00
}
/**
* Gets the bug report modal's content
*
* @return {*}
*/
2019-09-17 11:51:26 +02:00
getBugReportModal() {
return (
<View style={{
flex: 1,
padding: 20
}}>
<Title>{i18n.t('aboutScreen.bugs')}</Title>
<Text>
{i18n.t('aboutScreen.bugsDescription')}
</Text>
<Button
icon="email"
mode="contained"
style={{
marginTop: 20,
marginLeft: 'auto',
marginRight: 'auto',
}}
2020-03-10 11:33:22 +01:00
onPress={this.onPressMail}>
{i18n.t('aboutScreen.bugsMail')}
</Button>
<Button
icon="git"
mode="contained"
style={{
marginTop: 20,
marginLeft: 'auto',
marginRight: 'auto',
}}
2020-03-10 11:33:22 +01:00
onPress={this.onPressGit}>
{i18n.t('aboutScreen.bugsGit')}
</Button>
</View>
2019-09-17 11:51:26 +02:00
);
}
/**
* opens the bug report modal
*/
2019-09-17 11:51:26 +02:00
openBugReportModal() {
if (this.modalRef) {
this.modalRef.open();
2019-09-17 11:51:26 +02:00
}
}
/**
* Gets a card, depending on the given item's id
*
* @param item The item to show
* @return {*}
*/
getMainCard({item}: Object) {
switch (item.id) {
case 'app':
return this.getAppCard();
case 'team':
return this.getTeamCard();
case 'techno':
return this.getTechnoCard();
}
return <View/>;
}
/**
* Callback used when receiving the modal ref
*
* @param ref
*/
onModalRef(ref: Object) {
this.modalRef = ref;
}
2019-06-25 22:20:24 +02:00
render() {
return (
<View style={{padding: 5}}>
<CustomModal onRef={this.onModalRef}>
{this.getBugReportModal()}
</CustomModal>
<FlatList
style={{padding: 5}}
data={this.dataOrder}
renderItem={this.getMainCard}
/>
</View>
2019-06-25 22:20:24 +02:00
);
}
}
export default withTheme(AboutScreen);