CI / Build & Quality Checks (pull_request) Canceled after 0s
CI / Trigger Desktop Build (pull_request) Canceled after 0s
CI / Secret scan (gitleaks) (pull_request) Canceled after 0s
CI / Docker image build & smoke test (pull_request) Canceled after 0s
CI / Playwright smoke (e2e) (pull_request) Canceled after 0s
Settings (every page, pickers, the denoise tester) was in the entry chunk though it only renders when opened. Load it lazily behind a focusable spinner (it opens inside a FocusTrap), and warm the chunk when the app goes idle. SettingsPages and the status localStorage keys move to tiny modules so callers don't pull the dialog back in. sanitize-html (+postcss, htmlparser2) and chroma-js get their own vendor chunks; with Settings gone the chunk graph had dropped them into the entry chunk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
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>
|
|
);
|
|
}
|