App.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import 'react-native-gesture-handler';
  2. import 'expo-splash-screen';
  3. import { QueryClientProvider } from '@tanstack/react-query';
  4. import { NavigationContainer } from '@react-navigation/native';
  5. import { queryClient } from 'src/utils/queryClient';
  6. import * as Sentry from '@sentry/react-native';
  7. import Route from './Route';
  8. import { ConnectionProvider } from 'src/contexts/ConnectionContext';
  9. import ConnectionBanner from 'src/components/ConnectionBanner/ConnectionBanner';
  10. import { RegionProvider } from 'src/contexts/RegionContext';
  11. import { ErrorProvider, useError } from 'src/contexts/ErrorContext';
  12. import { useEffect, useState } from 'react';
  13. import { setupInterceptors } from 'src/utils/request';
  14. import { ErrorModal, WarningModal } from 'src/components';
  15. import React from 'react';
  16. import { Linking, Platform } from 'react-native';
  17. import { API_URL, APP_VERSION } from 'src/constants';
  18. import axios from 'axios';
  19. import { API } from 'src/types';
  20. const IOS_STORE_URL = 'https://apps.apple.com/app/id6502843543';
  21. const ANDROID_STORE_URL =
  22. 'https://play.google.com/store/apps/details?id=com.nomadmania.presentation';
  23. const routingInstrumentation = Sentry.reactNavigationIntegration({
  24. enableTimeToInitialDisplay: true
  25. });
  26. Sentry.init({
  27. dsn: 'https://c9b37005f4be22a17a582603ebc17598@o4507781200543744.ingest.de.sentry.io/4507781253824592',
  28. integrations: [Sentry.reactNativeTracingIntegration({ routingInstrumentation })],
  29. debug: false,
  30. ignoreErrors: ['Network Error', 'ECONNABORTED', 'timeout of 10000ms exceeded']
  31. });
  32. const App = () => {
  33. return (
  34. <QueryClientProvider client={queryClient}>
  35. <ErrorProvider>
  36. <InnerApp />
  37. </ErrorProvider>
  38. </QueryClientProvider>
  39. );
  40. };
  41. const InnerApp = () => {
  42. const errorContext = useError();
  43. const navigation = React.useRef(null);
  44. const [isUpdateAvailable, setIsUpdateAvailable] = useState(false);
  45. useEffect(() => {
  46. setupInterceptors(errorContext);
  47. }, [errorContext]);
  48. useEffect(() => {
  49. const checkLatestVersion = async () => {
  50. try {
  51. const response = await axios.get(API_URL + '/' + API.LATEST_VERSION, {
  52. headers: {
  53. 'App-Version': APP_VERSION,
  54. Platform: Platform.OS
  55. }
  56. });
  57. const { version } = response.data;
  58. const formatVersion = (versionString: string) => {
  59. return parseInt(versionString.replace(/\./g, ''), 10);
  60. };
  61. const currentVersionInt = formatVersion(APP_VERSION);
  62. const latestVersionInt = formatVersion(version);
  63. if (latestVersionInt > currentVersionInt) {
  64. setIsUpdateAvailable(true);
  65. }
  66. } catch (error) {
  67. console.error('Failed to check latest version:', error);
  68. }
  69. };
  70. checkLatestVersion();
  71. }, []);
  72. const handleUpdatePress = () => {
  73. const storeUrl = Platform.OS === 'ios' ? IOS_STORE_URL : ANDROID_STORE_URL;
  74. Linking.openURL(storeUrl).catch((err) => console.error('Failed to open store URL:', err));
  75. };
  76. return (
  77. <ConnectionProvider>
  78. <RegionProvider>
  79. <NavigationContainer
  80. ref={navigation}
  81. onReady={() => {
  82. routingInstrumentation.registerNavigationContainer(navigation);
  83. }}
  84. >
  85. <Route />
  86. <ConnectionBanner />
  87. <ErrorModal />
  88. <WarningModal
  89. isVisible={isUpdateAvailable}
  90. type="success"
  91. title="Update Available"
  92. message="A new version of the NomadMania app is available. Please update to the latest version."
  93. action={handleUpdatePress}
  94. onClose={() => setIsUpdateAvailable(false)}
  95. />
  96. </NavigationContainer>
  97. </RegionProvider>
  98. </ConnectionProvider>
  99. );
  100. };
  101. export default Sentry.wrap(App);