feat: check IndexedDB support (#1630)

* check indexed db support and display message

* fix typo
This commit is contained in:
Ajay Bura 2024-01-24 00:06:55 +11:00 committed by GitHub
parent ef2733df48
commit 983d533452
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 14 deletions

View file

@ -17,6 +17,7 @@ import { isAuthenticated } from '../../client/state/auth';
import Client from '../templates/client/Client'; import Client from '../templates/client/Client';
import { getLoginPath } from './pathUtils'; import { getLoginPath } from './pathUtils';
import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig'; import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig';
import { FeatureCheck } from './FeatureCheck';
const createRouter = (clientConfig: ClientConfig) => { const createRouter = (clientConfig: ClientConfig) => {
const { hashRouter } = clientConfig; const { hashRouter } = clientConfig;
@ -62,20 +63,22 @@ const createRouter = (clientConfig: ClientConfig) => {
// TODO: app crash boundary // TODO: app crash boundary
function App() { function App() {
return ( return (
<ClientConfigLoader <FeatureCheck>
fallback={() => <ConfigConfigLoading />} <ClientConfigLoader
error={(err, retry, ignore) => ( fallback={() => <ConfigConfigLoading />}
<ConfigConfigError error={err} retry={retry} ignore={ignore} /> error={(err, retry, ignore) => (
)} <ConfigConfigError error={err} retry={retry} ignore={ignore} />
> )}
{(clientConfig) => ( >
<ClientConfigProvider value={clientConfig}> {(clientConfig) => (
<JotaiProvider> <ClientConfigProvider value={clientConfig}>
<RouterProvider router={createRouter(clientConfig)} /> <JotaiProvider>
</JotaiProvider> <RouterProvider router={createRouter(clientConfig)} />
</ClientConfigProvider> </JotaiProvider>
)} </ClientConfigProvider>
</ClientConfigLoader> )}
</ClientConfigLoader>
</FeatureCheck>
); );
} }

View file

@ -0,0 +1,42 @@
import React, { ReactNode, useEffect } from 'react';
import { Box, Dialog, Text, config } from 'folds';
import { AsyncStatus, useAsyncCallback } from '../hooks/useAsyncCallback';
import { checkIndexedDBSupport } from '../utils/featureCheck';
import { SplashScreen } from '../components/splash-screen';
export function FeatureCheck({ children }: { children: ReactNode }) {
const [idbSupportState, checkIDBSupport] = useAsyncCallback(checkIndexedDBSupport);
useEffect(() => {
checkIDBSupport();
}, [checkIDBSupport]);
if (idbSupportState.status === AsyncStatus.Success && idbSupportState.data === false) {
return (
<SplashScreen>
<Box grow="Yes" alignItems="Center" justifyContent="Center">
<Dialog>
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
<Text>Missing Browser Feature</Text>
<Text size="T300" priority="400">
No IndexedDB support found. This application requires IndexedDB to store session
data locally. Please make sure your browser support IndexedDB and have it enabled.
</Text>
<Text size="T200">
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"
rel="noreferrer noopener"
target="_blank"
>
What is IndexedDB?
</a>
</Text>
</Box>
</Dialog>
</Box>
</SplashScreen>
);
}
return children;
}

View file

@ -0,0 +1,21 @@
export const checkIndexedDBSupport = async (): Promise<boolean> => {
const ts = new Date().getTime();
const dbName = `checkIndexedDBSupport-${ts}`;
return new Promise((resolve) => {
let db;
try {
db = indexedDB.open(dbName);
} catch {
resolve(false);
return;
}
db.onsuccess = () => {
resolve(true);
indexedDB.deleteDatabase(dbName);
};
db.onerror = () => {
resolve(false);
indexedDB.deleteDatabase(dbName);
};
});
};