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.

App.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // @flow
  2. import * as React from 'react';
  3. import {LogBox, Platform, SafeAreaView, View} from 'react-native';
  4. import {NavigationContainer} from '@react-navigation/native';
  5. import {Provider as PaperProvider} from 'react-native-paper';
  6. import {setSafeBounceHeight} from 'react-navigation-collapsible';
  7. import SplashScreen from 'react-native-splash-screen';
  8. import {OverflowMenuProvider} from 'react-navigation-header-buttons';
  9. import LocaleManager from './src/managers/LocaleManager';
  10. import AsyncStorageManager from './src/managers/AsyncStorageManager';
  11. import CustomIntroSlider from './src/components/Overrides/CustomIntroSlider';
  12. import type {CustomThemeType} from './src/managers/ThemeManager';
  13. import ThemeManager from './src/managers/ThemeManager';
  14. import MainNavigator from './src/navigation/MainNavigator';
  15. import AprilFoolsManager from './src/managers/AprilFoolsManager';
  16. import Update from './src/constants/Update';
  17. import ConnectionManager from './src/managers/ConnectionManager';
  18. import type {ParsedUrlDataType} from './src/utils/URLHandler';
  19. import URLHandler from './src/utils/URLHandler';
  20. import {setupStatusBar} from './src/utils/Utils';
  21. // Native optimizations https://reactnavigation.org/docs/react-native-screens
  22. // Crashes app when navigating away from webview on android 9+
  23. // enableScreens(true);
  24. LogBox.ignoreLogs([
  25. // collapsible headers cause this warning, just ignore as it is not an issue
  26. 'Non-serializable values were found in the navigation state',
  27. 'Cannot update a component from inside the function body of a different component',
  28. ]);
  29. type StateType = {
  30. isLoading: boolean,
  31. showIntro: boolean,
  32. showUpdate: boolean,
  33. showAprilFools: boolean,
  34. currentTheme: CustomThemeType | null,
  35. };
  36. export default class App extends React.Component<null, StateType> {
  37. navigatorRef: {current: null | NavigationContainer};
  38. defaultHomeRoute: string | null;
  39. defaultHomeData: {[key: string]: string};
  40. urlHandler: URLHandler;
  41. constructor() {
  42. super();
  43. this.state = {
  44. isLoading: true,
  45. showIntro: true,
  46. showUpdate: true,
  47. showAprilFools: false,
  48. currentTheme: null,
  49. };
  50. LocaleManager.initTranslations();
  51. this.navigatorRef = React.createRef();
  52. this.defaultHomeRoute = null;
  53. this.defaultHomeData = {};
  54. this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
  55. this.urlHandler.listen();
  56. setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 20);
  57. this.loadAssetsAsync().finally(() => {
  58. this.onLoadFinished();
  59. });
  60. }
  61. /**
  62. * The app has been started by an url, and it has been parsed.
  63. * Set a new default start route based on the data parsed.
  64. *
  65. * @param parsedData The data parsed from the url
  66. */
  67. onInitialURLParsed = (parsedData: ParsedUrlDataType) => {
  68. this.defaultHomeRoute = parsedData.route;
  69. this.defaultHomeData = parsedData.data;
  70. };
  71. /**
  72. * An url has been opened and parsed while the app was active.
  73. * Redirect the user to the screen according to parsed data.
  74. *
  75. * @param parsedData The data parsed from the url
  76. */
  77. onDetectURL = (parsedData: ParsedUrlDataType) => {
  78. // Navigate to nested navigator and pass data to the index screen
  79. const nav = this.navigatorRef.current;
  80. if (nav != null) {
  81. nav.navigate('home', {
  82. screen: 'index',
  83. params: {nextScreen: parsedData.route, data: parsedData.data},
  84. });
  85. }
  86. };
  87. /**
  88. * Updates the current theme
  89. */
  90. onUpdateTheme = () => {
  91. this.setState({
  92. currentTheme: ThemeManager.getCurrentTheme(),
  93. });
  94. setupStatusBar();
  95. };
  96. /**
  97. * Callback when user ends the intro. Save in preferences to avoid showing back the introSlides
  98. */
  99. onIntroDone = () => {
  100. this.setState({
  101. showIntro: false,
  102. showUpdate: false,
  103. showAprilFools: false,
  104. });
  105. AsyncStorageManager.set(
  106. AsyncStorageManager.PREFERENCES.showIntro.key,
  107. false,
  108. );
  109. AsyncStorageManager.set(
  110. AsyncStorageManager.PREFERENCES.updateNumber.key,
  111. Update.number,
  112. );
  113. AsyncStorageManager.set(
  114. AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key,
  115. false,
  116. );
  117. };
  118. /**
  119. * Async loading is done, finish processing startup data
  120. */
  121. onLoadFinished() {
  122. // Only show intro if this is the first time starting the app
  123. ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
  124. // Status bar goes dark if set too fast on ios
  125. if (Platform.OS === 'ios') setTimeout(setupStatusBar, 1000);
  126. else setupStatusBar();
  127. this.setState({
  128. isLoading: false,
  129. currentTheme: ThemeManager.getCurrentTheme(),
  130. showIntro: AsyncStorageManager.getBool(
  131. AsyncStorageManager.PREFERENCES.showIntro.key,
  132. ),
  133. showUpdate:
  134. AsyncStorageManager.getNumber(
  135. AsyncStorageManager.PREFERENCES.updateNumber.key,
  136. ) !== Update.number,
  137. showAprilFools:
  138. AprilFoolsManager.getInstance().isAprilFoolsEnabled() &&
  139. AsyncStorageManager.getBool(
  140. AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key,
  141. ),
  142. });
  143. SplashScreen.hide();
  144. }
  145. /**
  146. * Loads every async data
  147. *
  148. * @returns {Promise<void>}
  149. */
  150. loadAssetsAsync = async () => {
  151. await AsyncStorageManager.getInstance().loadPreferences();
  152. await ConnectionManager.getInstance()
  153. .recoverLogin()
  154. .catch(() => {});
  155. };
  156. /**
  157. * Renders the app based on loading state
  158. */
  159. render(): React.Node {
  160. const {state} = this;
  161. if (state.isLoading) {
  162. return null;
  163. }
  164. if (state.showIntro || state.showUpdate || state.showAprilFools) {
  165. return (
  166. <CustomIntroSlider
  167. onDone={this.onIntroDone}
  168. isUpdate={state.showUpdate && !state.showIntro}
  169. isAprilFools={state.showAprilFools && !state.showIntro}
  170. />
  171. );
  172. }
  173. return (
  174. <PaperProvider theme={state.currentTheme}>
  175. <OverflowMenuProvider>
  176. <View
  177. style={{
  178. backgroundColor: ThemeManager.getCurrentTheme().colors.background,
  179. flex: 1,
  180. }}>
  181. <SafeAreaView style={{flex: 1}}>
  182. <NavigationContainer
  183. theme={state.currentTheme}
  184. ref={this.navigatorRef}>
  185. <MainNavigator
  186. defaultHomeRoute={this.defaultHomeRoute}
  187. defaultHomeData={this.defaultHomeData}
  188. />
  189. </NavigationContainer>
  190. </SafeAreaView>
  191. </View>
  192. </OverflowMenuProvider>
  193. </PaperProvider>
  194. );
  195. }
  196. }