Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mmeissonnier-pass committed Jan 9, 2025
1 parent d27489f commit 5463f62
Show file tree
Hide file tree
Showing 18 changed files with 172 additions and 291 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ module.exports = {
['types', './src/types'],
['ui', './src/ui'],
['web', './src/web'],
['store', './src/store'],
],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.mjs'],
},
Expand Down
95 changes: 61 additions & 34 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { FunctionComponent, useEffect } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import 'react-native-gesture-handler' // @react-navigation
import 'react-native-get-random-values' // required for `uuid` module to work
import { LogBox, Platform, StatusBar } from 'react-native'
import CodePush from 'react-native-code-push'
import SplashScreen from 'react-native-lottie-splash-screen'
import { onlineManager } from 'react-query'

import 'react-native-get-random-values' // required for `uuid` module to work
import 'react-native-gesture-handler' // @react-navigation
// if __DEV__ import if you want to debug
// import './why-did-you-render'
if (process.env.NODE_ENV === 'development') {
Expand Down Expand Up @@ -41,8 +43,8 @@ import { BatchMessaging, BatchPush } from 'libs/react-native-batch'
import { configureGoogleSignin } from 'libs/react-native-google-sso/configureGoogleSignin'
import { SafeAreaProvider } from 'libs/react-native-save-area-provider'
import { ReactQueryClientProvider } from 'libs/react-query/ReactQueryClientProvider'
import { SplashScreenProvider } from 'libs/splashscreen'
import { ThemeProvider } from 'libs/styled'
import { clearNotification, setAppReady, setNotification, useAppStore } from 'store/useAppStore'
import { theme } from 'theme'
import { SnackBarProvider } from 'ui/components/snackBar/SnackBarContext'

Expand Down Expand Up @@ -81,13 +83,13 @@ const App: FunctionComponent = function () {
}, [])

return (
<SplashScreenProvider>
<NetInfoWrapper>
<RemoteConfigProvider>
<ReactQueryClientProvider>
<ThemeProvider theme={theme}>
<SafeAreaProvider>
<ErrorBoundary FallbackComponent={AsyncErrorBoundaryWithoutNavigation}>
<RemoteConfigProvider>
<ReactQueryClientProvider>
<ThemeProvider theme={theme}>
<SafeAreaProvider>
<SnackBarProvider>
<ErrorBoundary FallbackComponent={AsyncErrorBoundaryWithoutNavigation}>
<NetInfoWrapper>
<AnalyticsInitializer>
<SettingsWrapper>
<AuthWrapper>
Expand All @@ -96,23 +98,21 @@ const App: FunctionComponent = function () {
<FavoritesWrapper>
<SearchAnalyticsWrapper>
<SearchWrapper>
<SnackBarProvider>
<CulturalSurveyContextProvider>
<SubscriptionContextProvider>
<PushNotificationsWrapper>
<ShareAppWrapper>
<OnboardingWrapper>
<OfflineModeContainer>
<ScreenErrorProvider>
<AppNavigationContainer />
</ScreenErrorProvider>
</OfflineModeContainer>
</OnboardingWrapper>
</ShareAppWrapper>
</PushNotificationsWrapper>
</SubscriptionContextProvider>
</CulturalSurveyContextProvider>
</SnackBarProvider>
<CulturalSurveyContextProvider>
<SubscriptionContextProvider>
<PushNotificationsWrapper>
<ShareAppWrapper>
<OnboardingWrapper>
<OfflineModeContainer>
<ScreenErrorProvider>
<AppNavigationContainer />
</ScreenErrorProvider>
</OfflineModeContainer>
</OnboardingWrapper>
</ShareAppWrapper>
</PushNotificationsWrapper>
</SubscriptionContextProvider>
</CulturalSurveyContextProvider>
</SearchWrapper>
</SearchAnalyticsWrapper>
</FavoritesWrapper>
Expand All @@ -121,13 +121,13 @@ const App: FunctionComponent = function () {
</AuthWrapper>
</SettingsWrapper>
</AnalyticsInitializer>
</ErrorBoundary>
</SafeAreaProvider>
</ThemeProvider>
</ReactQueryClientProvider>
</RemoteConfigProvider>
</NetInfoWrapper>
</SplashScreenProvider>
</NetInfoWrapper>
</ErrorBoundary>
</SnackBarProvider>
</SafeAreaProvider>
</ThemeProvider>
</ReactQueryClientProvider>
</RemoteConfigProvider>
)
}

Expand All @@ -139,6 +139,33 @@ const AppWithMonitoring = eventMonitoring.wrap(AppWithoutMonitoring) as React.Co
}>
const AppWithCodepush = __DEV__ ? AppWithMonitoring : CodePush(config)(AppWithMonitoring)

// SIDE EFFECTS
useAppStore.subscribe(
(state) => state.isNetworkAvailable,
(isNetworkAvailable) => {
if (isNetworkAvailable === true) {
onlineManager.setOnline(true)
clearNotification()
} else if (isNetworkAvailable === false) {
onlineManager.setOnline(false)
setAppReady(true)
setNotification({
type: 'info',
message: 'Aucune connexion internet. Réessaie plus tard',
})
}
}
)

useAppStore.subscribe(
(state) => state.isAppReady,
(isAppReady) => {
if (isAppReady) {
SplashScreen.hide()
}
}
)

/**
* We have an import bug in the test file App.native.test.tsx with the new eventMonitoring wrapper : WEIRD !!! :
* Element type is invalid: expected a string (for built-in components) or a class/function (for composite components)
Expand Down
27 changes: 15 additions & 12 deletions src/features/auth/context/AuthContext.native.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react'

import { BatchProfile } from '__mocks__/@batch.com/react-native-plugin'
import * as jwt from '__mocks__/jwt-decode'
import { UserProfileResponse } from 'api/gen'
import { RefreshResponse, UserProfileResponse } from 'api/gen'
import { CURRENT_DATE } from 'features/auth/fixtures/fixtures'
import * as NavigationRef from 'features/navigation/navigationRef'
import { beneficiaryUser, nonBeneficiaryUser } from 'fixtures/user'
Expand All @@ -12,8 +12,7 @@ import { amplitude } from 'libs/amplitude'
import { decodedTokenWithRemainingLifetime, tokenRemainingLifetimeInMs } from 'libs/jwt/fixtures'
import { clearRefreshToken, getRefreshToken, saveRefreshToken } from 'libs/keychain/keychain'
import { eventMonitoring } from 'libs/monitoring'
import { NetInfoWrapper } from 'libs/network/NetInfoWrapper'
import { useNetInfo } from 'libs/network/useNetInfo'
import { useNetInfoContext as useNetInfoContextDefault } from 'libs/network/NetInfoWrapper'
import * as PackageJson from 'libs/packageJson'
import { QueryKeys } from 'libs/queryKeys'
import { StorageKey, storage } from 'libs/storage'
Expand All @@ -24,7 +23,8 @@ import { act, renderHook } from 'tests/utils'
import { useAuthContext } from './AuthContext'
import { AuthWrapper } from './AuthWrapper'

const mockedUseNetInfo = useNetInfo as jest.Mock
jest.mock('libs/network/NetInfoWrapper')
const mockUseNetInfoContext = useNetInfoContextDefault as jest.Mock

jest.mock('libs/amplitude/amplitude')

Expand Down Expand Up @@ -54,17 +54,25 @@ describe('AuthContext', () => {
describe('useAuthContext', () => {
beforeEach(() => {
mockServer.getApi<UserProfileResponse>('/v1/me', nonBeneficiaryUser)
mockServer.postApi<RefreshResponse>('/v1/refresh_access_token', {})
mockUseNetInfoContext.mockReturnValue({
isConnected: true,
isInternetReachable: true,
})
})

it('should not return user when logged in but no internet connection', async () => {
mockedUseNetInfo.mockReturnValueOnce({ isConnected: false, isInternetReachable: false })
mockUseNetInfoContext.mockReturnValueOnce({
isConnected: false,
isInternetReachable: false,
})
await saveRefreshToken('token')

const result = renderUseAuthContext()

await act(async () => {})

expect(result.current).toBeNull()
expect(result.current.user).toEqual({})
})

it('should return the user when logged in with internet connection', async () => {
Expand Down Expand Up @@ -278,12 +286,7 @@ describe('AuthContext', () => {

const renderUseAuthContext = () => {
const { result } = renderHook(useAuthContext, {
wrapper: ({ children }) =>
reactQueryProviderHOC(
<NetInfoWrapper>
<AuthWrapper>{children}</AuthWrapper>
</NetInfoWrapper>
),
wrapper: ({ children }) => reactQueryProviderHOC(<AuthWrapper>{children}</AuthWrapper>),
})

return result
Expand Down
8 changes: 1 addition & 7 deletions src/features/location/helpers/useLocationWidgetTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { LayoutChangeEvent, Platform } from 'react-native'

import { ScreenOrigin } from 'features/location/enums'
import { useLocation } from 'libs/location'
import { useSplashScreenContext } from 'libs/splashscreen'
import { storage } from 'libs/storage'

const START_OFFSET = 1000
Expand All @@ -12,9 +11,6 @@ const TOOLTIP_DISPLAY_DURATION = 8000
export const useLocationWidgetTooltip = (screenOrigin: ScreenOrigin) => {
const touchableRef = React.useRef<HTMLButtonElement>()

const { isSplashScreenHidden } = useSplashScreenContext()
const isNativeSplashScreenHidden = isSplashScreenHidden || Platform.OS === 'web'

const [widgetWidth, setWidgetWidth] = React.useState<number | undefined>()
const [isTooltipVisible, setIsTooltipVisible] = React.useState(false)
const hideTooltip = useCallback(() => setIsTooltipVisible(false), [setIsTooltipVisible])
Expand Down Expand Up @@ -52,8 +48,6 @@ export const useLocationWidgetTooltip = (screenOrigin: ScreenOrigin) => {
return
}

if (!isNativeSplashScreenHidden || !enableTooltip) return

const displayTooltipIfNeeded = async () => {
const timesLocationTooltipHasBeenDisplayed = Number(
await storage.readString('times_location_tooltip_has_been_displayed')
Expand All @@ -73,7 +67,7 @@ export const useLocationWidgetTooltip = (screenOrigin: ScreenOrigin) => {
clearTimeout(timeoutOff)
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- should only be called on startup
}, [isNativeSplashScreenHidden, geolocPosition])
}, [geolocPosition])

return {
isTooltipVisible,
Expand Down
27 changes: 12 additions & 15 deletions src/features/navigation/NavigationContainer/NavigationContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import { DefaultTheme, useTheme } from 'styled-components/native'

import { RootNavigator } from 'features/navigation/RootNavigator'
import { linking } from 'features/navigation/RootNavigator/linking'
import { useSplashScreenContext } from 'libs/splashscreen'
import { useInitialScreen } from 'features/navigation/RootNavigator/useInitialScreenConfig'
import { storage } from 'libs/storage'
import { setAppReady } from 'store/useAppStore'
import { LoadingPage } from 'ui/components/LoadingPage'

import { author } from '../../../../package.json'
Expand All @@ -33,12 +34,13 @@ const DOCUMENT_TITLE_OPTIONS: DocumentTitleOptions = {
}

export const AppNavigationContainer = () => {
const { hideSplashScreen } = useSplashScreenContext()
const theme = useTheme()

const [isNavReady, setIsNavReady] = useState(false)
const [navigationStateLoaded, setNavigationStateLoaded] = useState(false)
const [initialNavigationState, setInitialNavigationState] = useState<NavigationState>()

const initialScreen = useInitialScreen()

useEffect(() => {
async function restoreNavStateOnReload() {
try {
Expand All @@ -50,34 +52,29 @@ export const AppNavigationContainer = () => {

setInitialNavigationState(savedState)
} finally {
setIsNavReady(true)
setNavigationStateLoaded(true)
}
}
restoreNavStateOnReload()
}, [])

useEffect(() => {
if (isNavReady) {
hideSplashScreen?.()
}
}, [isNavReady, hideSplashScreen])

if (!isNavReady) {
return <LoadingPage />
if (isNavReady && navigationStateLoaded && initialScreen) {
setAppReady(true)
}

return (
return initialScreen ? (
<NavigationContainer
linking={linking}
initialState={initialNavigationState}
onStateChange={onNavigationStateChange}
onReady={() => setIsNavReady(true)}
fallback={<LoadingPage />}
ref={navigationRef}
documentTitle={DOCUMENT_TITLE_OPTIONS}
theme={getNavThemeConfig(theme)}>
<RootNavigator />
<RootNavigator initialScreen={initialScreen} />
</NavigationContainer>
)
) : null
}

export default AppNavigationContainer
Expand Down
18 changes: 5 additions & 13 deletions src/features/navigation/RootNavigator/RootNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import { PrivacyPolicy } from 'features/cookies/pages/PrivacyPolicy'
import { useCurrentRoute } from 'features/navigation/helpers/useCurrentRoute'
import { AccessibleTabBar } from 'features/navigation/RootNavigator/Header/AccessibleTabBar'
import { RootScreenNames } from 'features/navigation/RootNavigator/types'
import { useInitialScreen } from 'features/navigation/RootNavigator/useInitialScreenConfig'
import { withWebWrapper } from 'features/navigation/RootNavigator/withWebWrapper'
import { TabNavigationStateProvider } from 'features/navigation/TabBar/TabNavigationStateContext'
import { VenueMapFiltersStackNavigator } from 'features/navigation/VenueMapFiltersStackNavigator/VenueMapFiltersStackNavigator'
import { AccessibilityRole } from 'libs/accessibilityRole/accessibilityRole'
import { env } from 'libs/environment'
import { useSplashScreenContext } from 'libs/splashscreen'
import { storage } from 'libs/storage'
import { IconFactoryProvider } from 'ui/components/icons/IconFactoryProvider'
import { LoadingPage } from 'ui/components/LoadingPage'
Expand All @@ -38,7 +36,7 @@ const CheatcodesStackNavigator = lazy(async () => {
})

const RootStackNavigator = withWebWrapper(
({ initialRouteName }: { initialRouteName: RootScreenNames }) => {
({ initialRouteName }: { initialRouteName?: RootScreenNames }) => {
const { top } = useSafeAreaInsets()
return (
<IconFactoryProvider>
Expand Down Expand Up @@ -76,14 +74,11 @@ const RootStackNavigator = withWebWrapper(
}
)

export const RootNavigator: React.ComponentType = () => {
export const RootNavigator = ({ initialScreen }: { initialScreen?: RootScreenNames }) => {
const mainId = uuidv4()
const tabBarId = uuidv4()
const { showTabBar } = useTheme()
const { isLoggedIn } = useAuthContext()
const { isSplashScreenHidden } = useSplashScreenContext()

const initialScreen = useInitialScreen()

const currentRoute = useCurrentRoute()
const showHeaderQuickAccess = currentRoute && currentRoute.name === 'TabNavigator'
Expand All @@ -103,10 +98,6 @@ export const RootNavigator: React.ComponentType = () => {
}
}, [isLoggedIn])

if (!initialScreen) {
return <LoadingPage />
}

const mainAccessibilityRole: AccessibilityRole | undefined =
determineAccessibilityRole(currentRoute)

Expand All @@ -121,8 +112,9 @@ export const RootNavigator: React.ComponentType = () => {
<AccessibleTabBar id={tabBarId} />
</View>
) : null}
{/* The components below are those for which we do not want their rendering to happen while the splash is displayed. */}
{isSplashScreenHidden ? <PrivacyPolicy /> : null}
{/* The components below are those for which we do not want
their rendering to happen while the splash is displayed. */}
<PrivacyPolicy />
</TabNavigationStateProvider>
)
}
Expand Down
Loading

0 comments on commit 5463f62

Please sign in to comment.