feat: check IndexedDB support (#1630)
* check indexed db support and display message * fix typo
This commit is contained in:
parent
ef2733df48
commit
983d533452
3 changed files with 80 additions and 14 deletions
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
src/app/pages/FeatureCheck.tsx
Normal file
42
src/app/pages/FeatureCheck.tsx
Normal 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;
|
||||||
|
}
|
21
src/app/utils/featureCheck.ts
Normal file
21
src/app/utils/featureCheck.ts
Normal 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);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
Loading…
Reference in a new issue