feat(App): replace PageLoader with LazyLoader for improved loading experience
This commit is contained in:
parent
fc2ed1c321
commit
f1f4c6dc16
|
|
@ -13,6 +13,7 @@ import MediaManager from './components/MediaManager';
|
|||
import logoSvg from '../imports/logo.svg';
|
||||
import { useSettings } from './settings';
|
||||
import { WsProvider } from './ws';
|
||||
import { LazyLoader } from './components/ui/lazy-loader';
|
||||
|
||||
// Three.js lives only in RealityOverridePage — keep lazy so it doesn't load on startup.
|
||||
// CodeMirror/syntax-highlighter/ReactMarkdown live in MediaViewerEditor — lazy-loaded
|
||||
|
|
@ -47,13 +48,6 @@ type AppId =
|
|||
| 'reality-override'
|
||||
| 'reality-override-admin';
|
||||
|
||||
function PageLoader() {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full text-neutral-400">
|
||||
<Loader2 className="w-6 h-6 animate-spin" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const [currentPage, setCurrentPage] = useState<Page>('status');
|
||||
|
|
@ -314,7 +308,7 @@ function AppPage({ title, onBack }: { title: string; onBack: () => void }) {
|
|||
</header>
|
||||
|
||||
<main className="flex-1 overflow-y-auto">
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
<Suspense fallback={<LazyLoader />}>
|
||||
{pages[currentPage]}
|
||||
</Suspense>
|
||||
</main>
|
||||
|
|
|
|||
38
src/app/components/ui/lazy-loader.tsx
Normal file
38
src/app/components/ui/lazy-loader.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
export function LazyLoader() {
|
||||
const [pct, setPct] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const steps: [number, number][] = [
|
||||
[80, 30],
|
||||
[400, 60],
|
||||
[1200, 80],
|
||||
[2500, 92],
|
||||
];
|
||||
const timers = steps.map(([delay, val]) => setTimeout(() => setPct(val), delay));
|
||||
return () => timers.forEach(clearTimeout);
|
||||
}, []);
|
||||
|
||||
const duration =
|
||||
pct <= 30 ? '150ms' :
|
||||
pct <= 60 ? '500ms' :
|
||||
pct <= 80 ? '1000ms' : '1500ms';
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-neutral-950 z-40 flex flex-col items-center justify-center">
|
||||
<div className="absolute top-0 left-0 right-0 h-[2px] bg-neutral-800 overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-blue-500 transition-[width] ease-out"
|
||||
style={{ width: `${pct}%`, transitionDuration: duration }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-3 text-neutral-600">
|
||||
<Loader2 className="w-5 h-5 animate-spin" />
|
||||
<span className="text-xs tracking-wide">Loading…</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user