44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import React, { lazy, Suspense } from 'react';
|
|||
|
|
import { Box, Spinner, config } from 'folds';
|
||
|
|
import type { SettingsPages } from './pages';
|
||
|
|
|
||
|
|
// Settings is a large, rarely-open dialog (all its pages, pickers, the
|
||
|
|
// denoise tester…). Load it on first open instead of in the entry chunk, and
|
||
|
|
// warm the chunk once the app is idle so opening it rarely waits.
|
||
|
|
const loadSettings = () => import('./Settings');
|
||
|
|
const SettingsDialog = lazy(() => loadSettings().then((m) => ({ default: m.Settings })));
|
||
|
|
if (typeof window !== 'undefined') {
|
||
|
|
const warm = () => {
|
||
|
|
loadSettings().catch(() => undefined);
|
||
|
|
};
|
||
|
|
if ('requestIdleCallback' in window) window.requestIdleCallback(warm, { timeout: 10_000 });
|
||
|
|
else setTimeout(warm, 5_000);
|
||
|
|
}
|
||
|
|
|
||
|
|
type SettingsProps = {
|
||
|
|
initialPage?: SettingsPages;
|
||
|
|
requestClose: () => void;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function Settings(props: SettingsProps) {
|
||
|
|
return (
|
||
|
|
<Suspense
|
||
|
|
fallback={
|
||
|
|
// Settings opens inside a FocusTrap, which needs a tabbable node.
|
||
|
|
<Box
|
||
|
|
tabIndex={0}
|
||
|
|
role="status"
|
||
|
|
aria-label="Loading settings"
|
||
|
|
alignItems="Center"
|
||
|
|
justifyContent="Center"
|
||
|
|
style={{ padding: config.space.S700, outline: 'none' }}
|
||
|
|
>
|
||
|
|
<Spinner variant="Secondary" size="400" />
|
||
|
|
</Box>
|
||
|
|
}
|
||
|
|
>
|
||
|
|
<SettingsDialog {...props} />
|
||
|
|
</Suspense>
|
||
|
|
);
|
||
|
|
}
|