76 lines
3.2 KiB
TypeScript
76 lines
3.2 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { Provider as JotaiProvider } from 'jotai';
|
|
import { OverlayContainerProvider, PopOutContainerProvider, TooltipContainerProvider } from 'folds';
|
|
import { RouterProvider } from 'react-router-dom';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
|
|
import { ClientConfigLoader } from '../components/ClientConfigLoader';
|
|
import { ClientConfigProvider } from '../hooks/useClientConfig';
|
|
import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig';
|
|
import { FeatureCheck } from './FeatureCheck';
|
|
import { createRouter } from './Router';
|
|
import { ScreenSizeProvider, useScreenSize } from '../hooks/useScreenSize';
|
|
import { useCompositionEndTracking } from '../hooks/useComposingCheck';
|
|
import { installPushLanguageBridge } from '../utils/pushLanguageBridge';
|
|
|
|
const queryClient = new QueryClient();
|
|
|
|
// Dev-only: react-query-devtools must never ship to production. The dynamic
|
|
// import lives in a branch Vite statically eliminates (import.meta.env.DEV →
|
|
// false in prod), so Rollup drops the chunk entirely from the prod bundle.
|
|
const ReactQueryDevtools = import.meta.env.DEV
|
|
? React.lazy(() =>
|
|
import('@tanstack/react-query-devtools').then((m) => ({ default: m.ReactQueryDevtools }))
|
|
)
|
|
: null;
|
|
|
|
function App() {
|
|
const screenSize = useScreenSize();
|
|
useCompositionEndTracking();
|
|
|
|
// Mirror i18next's current language to both native (Capacitor
|
|
// Preferences → Java PushStrings) and the Service Worker
|
|
// (postMessage → IndexedDB) so push-notification fallbacks render
|
|
// in the language the user picked in-app, not whichever locale the
|
|
// device / browser happens to report. No cleanup — the listener is
|
|
// intentionally global for the app lifetime.
|
|
useEffect(() => {
|
|
installPushLanguageBridge();
|
|
}, []);
|
|
|
|
const portalContainer = document.getElementById('portalContainer') ?? undefined;
|
|
|
|
return (
|
|
<TooltipContainerProvider value={portalContainer}>
|
|
<PopOutContainerProvider value={portalContainer}>
|
|
<OverlayContainerProvider value={portalContainer}>
|
|
<ScreenSizeProvider value={screenSize}>
|
|
<FeatureCheck>
|
|
<ClientConfigLoader
|
|
fallback={() => <ConfigConfigLoading />}
|
|
error={(err, retry) => <ConfigConfigError error={err} retry={retry} />}
|
|
>
|
|
{(clientConfig) => (
|
|
<ClientConfigProvider value={clientConfig}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<JotaiProvider>
|
|
<RouterProvider router={createRouter(clientConfig, screenSize)} />
|
|
</JotaiProvider>
|
|
{ReactQueryDevtools && (
|
|
<React.Suspense fallback={null}>
|
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
</React.Suspense>
|
|
)}
|
|
</QueryClientProvider>
|
|
</ClientConfigProvider>
|
|
)}
|
|
</ClientConfigLoader>
|
|
</FeatureCheck>
|
|
</ScreenSizeProvider>
|
|
</OverlayContainerProvider>
|
|
</PopOutContainerProvider>
|
|
</TooltipContainerProvider>
|
|
);
|
|
}
|
|
|
|
export default App;
|