diff --git a/frontend/src/components/dashboard/DashboardPage.tsx b/frontend/src/components/dashboard/DashboardPage.tsx index 00263cc..7aa0f44 100644 --- a/frontend/src/components/dashboard/DashboardPage.tsx +++ b/frontend/src/components/dashboard/DashboardPage.tsx @@ -44,16 +44,35 @@ export default function DashboardPage() { const dropdownRef = useRef(null); const [clockNow, setClockNow] = useState(() => new Date()); - // Live clock — synced to the minute boundary + // Live clock — synced to the minute boundary, re-syncs after tab sleep/resume useEffect(() => { let intervalId: ReturnType; - // Wait until the next :00 second mark, then tick every 60s - const msUntilNextMinute = (60 - new Date().getSeconds()) * 1000 - new Date().getMilliseconds(); - const timeoutId = setTimeout(() => { + let timeoutId: ReturnType; + + function startClock() { + clearTimeout(timeoutId); + clearInterval(intervalId); setClockNow(new Date()); - intervalId = setInterval(() => setClockNow(new Date()), 60_000); - }, msUntilNextMinute); - return () => { clearTimeout(timeoutId); clearInterval(intervalId); }; + const msUntilNextMinute = (60 - new Date().getSeconds()) * 1000 - new Date().getMilliseconds(); + timeoutId = setTimeout(() => { + setClockNow(new Date()); + intervalId = setInterval(() => setClockNow(new Date()), 60_000); + }, msUntilNextMinute); + } + + startClock(); + + // Re-sync when tab becomes visible again (after sleep/background throttle) + function handleVisibility() { + if (document.visibilityState === 'visible') startClock(); + } + document.addEventListener('visibilitychange', handleVisibility); + + return () => { + clearTimeout(timeoutId); + clearInterval(intervalId); + document.removeEventListener('visibilitychange', handleVisibility); + }; }, []); // Click outside to close dropdown diff --git a/frontend/src/components/layout/AmbientBackground.tsx b/frontend/src/components/layout/AppAmbientBackground.tsx similarity index 97% rename from frontend/src/components/layout/AmbientBackground.tsx rename to frontend/src/components/layout/AppAmbientBackground.tsx index d2c0bed..e6d5715 100644 --- a/frontend/src/components/layout/AmbientBackground.tsx +++ b/frontend/src/components/layout/AppAmbientBackground.tsx @@ -8,7 +8,7 @@ * Also renders a noise texture for tactile depth and a radial vignette * to darken edges and draw focus to center content. */ -export default function AmbientBackground() { +export default function AppAmbientBackground() { return (