diff --git a/src/components/FooterLogo/FooterLogo.jsx b/src/components/FooterLogo/FooterLogo.jsx index 938937d560..6df10ff2d2 100644 --- a/src/components/FooterLogo/FooterLogo.jsx +++ b/src/components/FooterLogo/FooterLogo.jsx @@ -1,6 +1,6 @@ import React from 'react' import { useClient, useQuery } from 'cozy-client' -import { buildContextQuery } from 'queries' +import { makeContextQuery } from 'queries' import Divider from 'cozy-ui/transpiled/react/Divider' import { useCozyTheme } from 'cozy-ui/transpiled/react/providers/CozyTheme' @@ -9,8 +9,10 @@ export const FooterLogo = () => { const { type } = useCozyTheme() const rootURL = client.getStackClient().uri - const contextQuery = buildContextQuery() - const { data } = useQuery(contextQuery.definition, contextQuery.options) + const { data } = useQuery( + makeContextQuery.definition, + makeContextQuery.options + ) const logos = data?.logos?.home?.light || [] const secondaries = logos.filter(logos => logos.type === 'secondary') diff --git a/src/containers/App.jsx b/src/containers/App.jsx index cf06590779..aadd0ae61d 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -1,8 +1,8 @@ /* global __SIMULATE_FLAGSHIP__ */ -import React, { useEffect, useState } from 'react' +import React, { useState } from 'react' import { Navigate, Route } from 'react-router-dom' -import flag, { enable as enableFlags } from 'cozy-flags' +import flag from 'cozy-flags' import minilog from 'cozy-minilog' import { useQuery } from 'cozy-client' import { useWebviewIntent } from 'cozy-intent' @@ -25,12 +25,10 @@ import IntentRedirect from 'components/IntentRedirect' import MoveModal from 'components/MoveModal' import StoreRedirection from 'components/StoreRedirection' import BackupNotification from 'components/BackupNotification/BackupNotification' -import appEntryPoint from 'components/appEntryPoint' import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints' import { BackgroundContainer } from 'components/BackgroundContainer' import { FLAG_FAB_BUTTON_ENABLED } from 'components/AddButton/helpers' import { MainView } from 'components/MainView' -import { toFlagNames } from './toFlagNames' import { Konnector } from 'components/Konnector' import DefaultRedirectionSnackbar from 'components/DefaultRedirectionSnackbar/DefaultRedirectionSnackbar' import ReloadFocus from './ReloadFocus' @@ -39,27 +37,22 @@ import { formatShortcuts } from 'components/Shortcuts/utils' import { mkHomeMagicFolderConn, mkHomeCustomShorcutsConn, - mkHomeCustomShorcutsDirConn, - contextQuery + mkHomeCustomShorcutsDirConn } from 'queries' +import { useFetchInitialData } from 'hooks/useFetchInitialData' import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n' import SectionDialog from 'components/Sections/SectionDialog' import { SentryRoutes } from 'lib/sentry' +import '../flags' window.flag = window.flag || flag window.minilog = minilog -const App = ({ accounts, konnectors, triggers }) => { +const App = () => { const { isMobile } = useBreakpoints() const [contentWrapper, setContentWrapper] = useState(undefined) - const [isFetching, setIsFetching] = useState( - [accounts, konnectors, triggers].some(collection => - ['pending', 'loading'].includes(collection.fetchStatus) - ) - ) - const [hasError, setHasError] = useState(false) - const [isReady, setIsReady] = useState(false) - const [appsReady, setAppsReady] = useState(false) + + const [didInit, setDidInit] = useState(false) const webviewIntent = useWebviewIntent() const theme = useCozyTheme() @@ -93,48 +86,28 @@ const App = ({ accounts, konnectors, triggers }) => { const shortcutsDirectories = canHaveShortcuts ? formatShortcuts(folders, customHomeShortcuts) : null - const context = useQuery(contextQuery.definition, contextQuery.options) + + const { isFetching, hasError } = useFetchInitialData() const showAssistantForMobile = isFlagshipApp() ? flag('cozy.searchbar.enabled-for-flagship') : flag('cozy.searchbar.enabled') && isMobile - useEffect(() => { - setIsFetching( - [accounts, konnectors, triggers, context].some(collection => - ['pending', 'loading'].includes(collection.fetchStatus) - ) - ) - setHasError( - [accounts, konnectors, triggers, context].find( - collection => collection.fetchStatus === 'failed' - ) - ) - }, [accounts, konnectors, triggers, context]) - - if (context?.attributes?.features) { - const flags = toFlagNames(context.attributes.features) - enableFlags(flags) - } - - useEffect(() => { - setIsReady( - appsReady && - !hasError && - !isFetching && - shortcutsDirectories !== undefined - ) - }, [appsReady, hasError, isFetching, shortcutsDirectories]) - - useEffect(() => { - if (isReady && webviewIntent) { + if ( + !didInit && + !hasError && + !isFetching && + shortcutsDirectories !== undefined + ) { + if (webviewIntent) { webviewIntent.call('setTheme', theme.variant) webviewIntent.call('hideSplashScreen') } - if (isReady && !webviewIntent && __SIMULATE_FLAGSHIP__) { + if (!webviewIntent && __SIMULATE_FLAGSHIP__) { document.getElementById('splashscreen').style.display = 'none' } - }, [isReady, theme, webviewIntent]) + setDidInit(true) + } return ( <> @@ -145,7 +118,7 @@ const App = ({ accounts, konnectors, triggers }) => {
setContentWrapper(div) : null} + ref={didInit ? div => setContentWrapper(div) : null} > @@ -205,4 +178,4 @@ const App = ({ accounts, konnectors, triggers }) => { ) } -export default appEntryPoint(App) +export default App diff --git a/src/hooks/useFetchInitialData.jsx b/src/hooks/useFetchInitialData.jsx new file mode 100644 index 0000000000..24ab223aaa --- /dev/null +++ b/src/hooks/useFetchInitialData.jsx @@ -0,0 +1,61 @@ +import { useEffect, useRef } from 'react' +import { useQuery } from 'cozy-client' +import { + makeAccountsQuery, + makeAppsQuery, + makeKonnectorsQuery, + makeTriggersQuery +} from 'queries' +import log from 'cozy-logger' + +export const useFetchInitialData = () => { + const accountsQuery = useQuery( + makeAccountsQuery.definition, + makeAccountsQuery.options + ) + const konnectorsQuery = useQuery( + makeKonnectorsQuery.definition, + makeKonnectorsQuery.options + ) + const appsQuery = useQuery(makeAppsQuery.definition, makeAppsQuery.options) + const triggersQuery = useQuery( + makeTriggersQuery.definition, + makeTriggersQuery.options + ) + + // eslint-disable-next-line react-hooks/exhaustive-deps + const allQueries = [accountsQuery, konnectorsQuery, appsQuery, triggersQuery] + + const startTime = useRef(null) + const loggedTime = useRef(false) + + useEffect(() => { + if (startTime.current === null) { + startTime.current = performance.now() + } + + const allFetched = allQueries.every(query => query.fetchStatus === 'loaded') + + if (allFetched && !loggedTime.current) { + const endTime = performance.now() + log('info', `Required data fetched in ${endTime - startTime.current} ms`) + loggedTime.current = true + } + }, [allQueries]) + + const isFetching = allQueries.some( + query => query.fetchStatus === 'loading' || query.fetchStatus === 'pending' + ) + const hasError = allQueries.some(query => query.fetchStatus === 'failed') + + return { + isFetching, + hasError, + data: { + accounts: accountsQuery.data, + konnectors: konnectorsQuery.data, + apps: appsQuery.data, + triggers: triggersQuery.data + } + } +} diff --git a/src/queries.js b/src/queries.js index 59083a2ca4..a5ae382f29 100644 --- a/src/queries.js +++ b/src/queries.js @@ -14,6 +14,22 @@ export const konnectorsConn = { fetchPolicy: defaultFetchPolicy } +export const makeAppsQuery = { + definition: () => Q('io.cozy.apps'), + options: { + as: 'io.cozy.apps', + fetchPolicy: defaultFetchPolicy + } +} + +export const makeKonnectorsQuery = { + definition: () => Q('io.cozy.konnectors'), + options: { + as: 'io.cozy.konnectors', + fetchPolicy: defaultFetchPolicy + } +} + export const makeTriggersQuery = { definition: () => { return Q('io.cozy.triggers') @@ -133,14 +149,14 @@ export const mkHomeCustomShorcutsConn = foldersId => { } } -export const buildContextQuery = () => ({ +export const makeContextQuery = { definition: () => Q('io.cozy.settings').getById('io.cozy.settings.context'), options: { as: 'io.cozy.settings/io.cozy.settings.context', fetchPolicy: defaultFetchPolicy, singleDocData: true } -}) +} export const buildExistingTimeseriesGeojsonQuery = () => ({ definition: Q('io.cozy.timeseries.geojson') @@ -153,12 +169,3 @@ export const buildExistingTimeseriesGeojsonQuery = () => ({ fetchPolicy: CozyClient.fetchPolicies.olderThan(60 * 60 * 24 * 365 * 1000) } }) - -export const contextQuery = { - definition: Q('io.cozy.settings').getById('io.cozy.settings.context'), - options: { - as: 'io.cozy.settings/io.cozy.settings.context', - fetchPolicy: defaultFetchPolicy, - singleDocData: true - } -}