Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AboutScreen.js 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // @flow
  2. import * as React from 'react';
  3. import {FlatList, Linking, Platform, Image} from 'react-native';
  4. import i18n from 'i18n-js';
  5. import {Avatar, Card, List, Title, withTheme} from 'react-native-paper';
  6. import {StackNavigationProp} from '@react-navigation/stack';
  7. import packageJson from '../../../package.json';
  8. import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
  9. import APP_LOGO from '../../../assets/android.icon.png';
  10. import type {
  11. CardTitleIconPropsType,
  12. ListIconPropsType,
  13. } from '../../constants/PaperStyles';
  14. type ListItemType = {
  15. onPressCallback: () => void,
  16. icon: string,
  17. text: string,
  18. showChevron: boolean,
  19. };
  20. const links = {
  21. appstore: 'https://apps.apple.com/us/app/campus-amicale-insat/id1477722148',
  22. playstore:
  23. 'https://play.google.com/store/apps/details?id=fr.amicaleinsat.application',
  24. git:
  25. 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/README.md',
  26. changelog:
  27. 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/Changelog.md',
  28. license:
  29. 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/src/branch/master/LICENSE',
  30. authorMail:
  31. 'mailto:vergnet@etud.insa-toulouse.fr?' +
  32. 'subject=' +
  33. 'Application Amicale INSA Toulouse' +
  34. '&body=' +
  35. 'Coucou !\n\n',
  36. authorLinkedin: 'https://www.linkedin.com/in/arnaud-vergnet-434ba5179/',
  37. yohanMail:
  38. 'mailto:ysimard@etud.insa-toulouse.fr?' +
  39. 'subject=' +
  40. 'Application Amicale INSA Toulouse' +
  41. '&body=' +
  42. 'Coucou !\n\n',
  43. yohanLinkedin: 'https://www.linkedin.com/in/yohan-simard',
  44. react: 'https://facebook.github.io/react-native/',
  45. meme: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
  46. };
  47. type PropsType = {
  48. navigation: StackNavigationProp,
  49. };
  50. /**
  51. * Opens a link in the device's browser
  52. * @param link The link to open
  53. */
  54. function openWebLink(link: string) {
  55. Linking.openURL(link);
  56. }
  57. /**
  58. * Class defining an about screen. This screen shows the user information about the app and it's author.
  59. */
  60. class AboutScreen extends React.Component<PropsType> {
  61. /**
  62. * Data to be displayed in the app card
  63. */
  64. appData = [
  65. {
  66. onPressCallback: () => {
  67. openWebLink(Platform.OS === 'ios' ? links.appstore : links.playstore);
  68. },
  69. icon: Platform.OS === 'ios' ? 'apple' : 'google-play',
  70. text:
  71. Platform.OS === 'ios'
  72. ? i18n.t('screens.about.appstore')
  73. : i18n.t('screens.about.playstore'),
  74. showChevron: true,
  75. },
  76. {
  77. onPressCallback: () => {
  78. const {navigation} = this.props;
  79. navigation.navigate('feedback');
  80. },
  81. icon: 'bug',
  82. text: i18n.t('screens.feedback.homeButtonTitle'),
  83. showChevron: true,
  84. },
  85. {
  86. onPressCallback: () => {
  87. openWebLink(links.git);
  88. },
  89. icon: 'git',
  90. text: 'Git',
  91. showChevron: true,
  92. },
  93. {
  94. onPressCallback: () => {
  95. openWebLink(links.changelog);
  96. },
  97. icon: 'refresh',
  98. text: i18n.t('screens.about.changelog'),
  99. showChevron: true,
  100. },
  101. {
  102. onPressCallback: () => {
  103. openWebLink(links.license);
  104. },
  105. icon: 'file-document',
  106. text: i18n.t('screens.about.license'),
  107. showChevron: true,
  108. },
  109. ];
  110. /**
  111. * Data to be displayed in the author card
  112. */
  113. authorData = [
  114. {
  115. onPressCallback: () => {
  116. openWebLink(links.meme);
  117. },
  118. icon: 'account-circle',
  119. text: 'Arnaud VERGNET',
  120. showChevron: false,
  121. },
  122. {
  123. onPressCallback: () => {
  124. openWebLink(links.authorMail);
  125. },
  126. icon: 'email',
  127. text: i18n.t('screens.about.authorMail'),
  128. showChevron: true,
  129. },
  130. {
  131. onPressCallback: () => {
  132. openWebLink(links.authorLinkedin);
  133. },
  134. icon: 'linkedin',
  135. text: 'Linkedin',
  136. showChevron: true,
  137. },
  138. ];
  139. /**
  140. * Data to be displayed in the additional developer card
  141. */
  142. additionalDevData = [
  143. {
  144. onPressCallback: () => {},
  145. icon: 'account',
  146. text: 'Yohan SIMARD',
  147. showChevron: false,
  148. },
  149. {
  150. onPressCallback: () => {
  151. openWebLink(links.yohanMail);
  152. },
  153. icon: 'email',
  154. text: i18n.t('screens.about.authorMail'),
  155. showChevron: true,
  156. },
  157. {
  158. onPressCallback: () => {
  159. openWebLink(links.yohanLinkedin);
  160. },
  161. icon: 'linkedin',
  162. text: 'Linkedin',
  163. showChevron: true,
  164. },
  165. ];
  166. /**
  167. * Data to be displayed in the technologies card
  168. */
  169. technoData = [
  170. {
  171. onPressCallback: () => {
  172. openWebLink(links.react);
  173. },
  174. icon: 'react',
  175. text: i18n.t('screens.about.reactNative'),
  176. showChevron: true,
  177. },
  178. {
  179. onPressCallback: () => {
  180. const {navigation} = this.props;
  181. navigation.navigate('dependencies');
  182. },
  183. icon: 'developer-board',
  184. text: i18n.t('screens.about.libs'),
  185. showChevron: true,
  186. },
  187. ];
  188. /**
  189. * Order of information cards
  190. */
  191. dataOrder = [
  192. {
  193. id: 'app',
  194. },
  195. {
  196. id: 'team',
  197. },
  198. {
  199. id: 'techno',
  200. },
  201. ];
  202. /**
  203. * Gets the app card showing information and links about the app.
  204. *
  205. * @return {*}
  206. */
  207. getAppCard(): React.Node {
  208. return (
  209. <Card style={{marginBottom: 10}}>
  210. <Card.Title
  211. title="Campus"
  212. subtitle={packageJson.version}
  213. left={(iconProps: CardTitleIconPropsType): React.Node => (
  214. <Image
  215. size={iconProps.size}
  216. source={APP_LOGO}
  217. style={{width: iconProps.size, height: iconProps.size}}
  218. />
  219. )}
  220. />
  221. <Card.Content>
  222. <FlatList
  223. data={this.appData}
  224. keyExtractor={this.keyExtractor}
  225. renderItem={this.getCardItem}
  226. />
  227. </Card.Content>
  228. </Card>
  229. );
  230. }
  231. /**
  232. * Gets the team card showing information and links about the team
  233. *
  234. * @return {*}
  235. */
  236. getTeamCard(): React.Node {
  237. return (
  238. <Card style={{marginBottom: 10}}>
  239. <Card.Title
  240. title={i18n.t('screens.about.team')}
  241. left={(iconProps: CardTitleIconPropsType): React.Node => (
  242. <Avatar.Icon size={iconProps.size} icon="account-multiple" />
  243. )}
  244. />
  245. <Card.Content>
  246. <Title>{i18n.t('screens.about.author')}</Title>
  247. <FlatList
  248. data={this.authorData}
  249. keyExtractor={this.keyExtractor}
  250. listKey="1"
  251. renderItem={this.getCardItem}
  252. />
  253. <Title>{i18n.t('screens.about.additionalDev')}</Title>
  254. <FlatList
  255. data={this.additionalDevData}
  256. keyExtractor={this.keyExtractor}
  257. listKey="2"
  258. renderItem={this.getCardItem}
  259. />
  260. </Card.Content>
  261. </Card>
  262. );
  263. }
  264. /**
  265. * Gets the techno card showing information and links about the technologies used in the app
  266. *
  267. * @return {*}
  268. */
  269. getTechnoCard(): React.Node {
  270. return (
  271. <Card style={{marginBottom: 10}}>
  272. <Card.Content>
  273. <Title>{i18n.t('screens.about.technologies')}</Title>
  274. <FlatList
  275. data={this.technoData}
  276. keyExtractor={this.keyExtractor}
  277. renderItem={this.getCardItem}
  278. />
  279. </Card.Content>
  280. </Card>
  281. );
  282. }
  283. /**
  284. * Gets a chevron icon
  285. *
  286. * @param props
  287. * @return {*}
  288. */
  289. static getChevronIcon(props: ListIconPropsType): React.Node {
  290. return (
  291. <List.Icon color={props.color} style={props.style} icon="chevron-right" />
  292. );
  293. }
  294. /**
  295. * Gets a custom list item icon
  296. *
  297. * @param item The item to show the icon for
  298. * @param props
  299. * @return {*}
  300. */
  301. static getItemIcon(item: ListItemType, props: ListIconPropsType): React.Node {
  302. return (
  303. <List.Icon color={props.color} style={props.style} icon={item.icon} />
  304. );
  305. }
  306. /**
  307. * Gets a clickable card item to be rendered inside a card.
  308. *
  309. * @returns {*}
  310. */
  311. getCardItem = ({item}: {item: ListItemType}): React.Node => {
  312. const getItemIcon = (props: ListIconPropsType): React.Node =>
  313. AboutScreen.getItemIcon(item, props);
  314. if (item.showChevron) {
  315. return (
  316. <List.Item
  317. title={item.text}
  318. left={getItemIcon}
  319. right={AboutScreen.getChevronIcon}
  320. onPress={item.onPressCallback}
  321. />
  322. );
  323. }
  324. return (
  325. <List.Item
  326. title={item.text}
  327. left={getItemIcon}
  328. onPress={item.onPressCallback}
  329. />
  330. );
  331. };
  332. /**
  333. * Gets a card, depending on the given item's id
  334. *
  335. * @param item The item to show
  336. * @return {*}
  337. */
  338. getMainCard = ({item}: {item: {id: string}}): React.Node => {
  339. switch (item.id) {
  340. case 'app':
  341. return this.getAppCard();
  342. case 'team':
  343. return this.getTeamCard();
  344. case 'techno':
  345. return this.getTechnoCard();
  346. default:
  347. return null;
  348. }
  349. };
  350. /**
  351. * Extracts a key from the given item
  352. *
  353. * @param item The item to extract the key from
  354. * @return {string} The extracted key
  355. */
  356. keyExtractor = (item: ListItemType): string => item.icon;
  357. render(): React.Node {
  358. return (
  359. <CollapsibleFlatList
  360. style={{padding: 5}}
  361. data={this.dataOrder}
  362. renderItem={this.getMainCard}
  363. />
  364. );
  365. }
  366. }
  367. export default withTheme(AboutScreen);