import React, { useState } from 'react'; import { AppState, LogBox, type Permission, PermissionsAndroid, Platform, StatusBar, } from 'react-native'; import { Provider } from 'react-redux'; import { init as initApm } from '@cobo/apm-rum-react-native'; import { PersistGate } from 'redux-persist/integration/react'; import { NavigationContainer } from '@react-navigation/native'; import * as Sentry from '@sentry/react-native'; import codePush from 'react-native-code-push'; import AsyncStorage from '@react-native-async-storage/async-storage'; import CodePush from 'react-native-code-push'; import store, { persistor } from './src/store/store'; import { navigationRef } from './src/components/utlis/navigationUtlis'; import FullScreenLoader from './RN-UI-LIB/src/components/FullScreenLoader'; import { toastConfigs, ToastContainer } from './RN-UI-LIB/src/components/toast'; import { APM_APP_NAME, APM_BASE_URL, ENV } from './src/constants/config'; import { COLORS } from './RN-UI-LIB/src/styles/colors'; import { CLICKSTREAM_EVENT_NAMES, LocalStorageKeys } from './src/common/Constants'; import Permissions from './src/screens/permissions/Permissions'; import { setJsErrorHandler } from './src/services/exception-handler.service'; import SuspenseLoader from './RN-UI-LIB/src/components/suspense_loader/SuspenseLoader'; import ErrorBoundary from './src/common/ErrorBoundary'; import { type TDocumentObj } from './src/screens/caseDetails/interface'; import AuthRouter from './src/screens/auth/AuthRouter'; import { initSentry } from './src/components/utlis/sentry'; import { getPermissionsToRequest, getPermissionsToValidate, } from './src/components/utlis/PermissionUtils'; import usePolling from './src/hooks/usePolling'; import { MILLISECONDS_IN_A_SECOND } from './RN-UI-LIB/src/utlis/common'; import { setItem } from './src/components/utlis/storageHelper'; import { StorageKeys } from './src/types/storageKeys'; import dayJs from 'dayjs'; import { GlobalImageMap, hydrateGlobalImageMap } from './src/common/CachedImage'; import analytics from '@react-native-firebase/analytics'; import handleUpdatedConfigureValuesFromFirebase from './src/services/firebaseFetchAndUpdate.service'; import { addClickstreamEvent } from './src/services/clickstreamEventService'; initSentry(); if (ENV !== 'prod') { // mockApiServer(); } setJsErrorHandler(); LogBox.ignoreAllLogs(); export let GlobalDocumentMap: Record = {}; async function checkCodePushAndSync() { try { await CodePush.sync({ installMode: codePush.InstallMode.IMMEDIATE, }); } catch (error) {} } function handleAppStateChange(nextAppState: any) { if (nextAppState == 'active') { checkCodePushAndSync(); } } const PERMISSION_CHECK_POLL_INTERVAL = 5 * MILLISECONDS_IN_A_SECOND; function App() { const [permissions, setPermissions] = React.useState(true); const [isGlobalDocumentMapLoaded, setIsGlobalDocumentMapLoaded] = React.useState(false); const [routeName, setRouteName] = useState('Unknown'); const askForPermissions = async () => { const permissionsToRequest = await getPermissionsToRequest(); if (Platform.OS === 'android') { PermissionsAndroid.requestMultiple(permissionsToRequest) .then(async (result) => { let isAllPermissionsGranted = true; for (const permission in result) { if (result?.[permission as Permission] !== PermissionsAndroid.RESULTS.GRANTED) { isAllPermissionsGranted = false; break; } } setPermissions(isAllPermissionsGranted); }) .catch((err) => { setPermissions(false); }); } }; const getActiveRouteName = (state) => { if (!state || typeof state.index !== 'number') { return 'Unknown'; } const route = state.routes[state.index]; if (route.state) { return getActiveRouteName(route.state); } return route?.name || ''; }; async function setForegroundTimeStampAndClickstream() { const now = dayJs().toString(); await setItem(StorageKeys.APP_FOREGROUND_TIMESTAMP, now); addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_APP_FOREGROUND, { now }); } usePolling(askForPermissions, PERMISSION_CHECK_POLL_INTERVAL); initApm({ serviceName: APM_APP_NAME, serverUrl: APM_BASE_URL, serviceVersion: '1.0.0', environment: ENV, active: true, }); React.useEffect(() => { askForPermissions(); const appStateChange = AppState.addEventListener('change', async (change) => { handleAppStateChange(change); hydrateGlobalImageMap(); }); (async () => { const data = await AsyncStorage.getItem(LocalStorageKeys.GLOBAL_DOCUMENT_MAP); if (data) { const parsedData = JSON.parse(data); GlobalDocumentMap = parsedData; } setIsGlobalDocumentMapLoaded(true); })(); checkCodePushAndSync(); handleUpdatedConfigureValuesFromFirebase(); setForegroundTimeStampAndClickstream(); return () => { appStateChange.remove(); }; }, []); return ( } persistor={persistor} > { const currentRouteName = getActiveRouteName(state); if (routeName !== currentRouteName) { await analytics().logScreenView({ screen_name: currentRouteName, screen_class: currentRouteName, }); await analytics().logEvent('screen_view', { screen_name: currentRouteName, screen_class: currentRouteName, }); setRouteName(currentRouteName); } }} > } loading={!isGlobalDocumentMapLoaded} children={ {permissions ? : } } /> ); } const AppWithSentry = Sentry.wrap(App); export default AppWithSentry;