Application Android et IOS pour l'amicale des élèves
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 11KB

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