diff --git a/client/src/App.tsx b/client/src/App.tsx index 42e0836..e153c3c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,6 +1,4 @@ import { useCallback } from 'react'; -import { ApolloProvider } from '@apollo/client'; -import { client } from './graphql/client'; import { DesktopLayout } from './layouts/DesktopLayout'; import { MobileLayout } from './layouts/MobileLayout'; import { UserSelection } from './components/UserSelection'; @@ -64,37 +62,35 @@ export function App() { } return ( - -
- {deviceType === 'desktop' ? ( - - ) : ( - - )} -
-
+
+ {deviceType === 'desktop' ? ( + + ) : ( + + )} +
); } diff --git a/client/src/components/Screensaver.tsx b/client/src/components/Screensaver.tsx index 1706a13..e24acfb 100644 --- a/client/src/components/Screensaver.tsx +++ b/client/src/components/Screensaver.tsx @@ -155,18 +155,29 @@ export function Screensaver({ onClose }: ScreensaverProps) { const animationRef = useRef(); const { primaryColor } = useThemeStore(); const [lastClearTime, setLastClearTime] = useState(Date.now()); + const [interactionEnabled, setInteractionEnabled] = useState(false); useEffect(() => { + console.log('Screensaver: useEffect triggered'); const canvas = canvasRef.current; - if (!canvas) return; + if (!canvas) { + console.error('Screensaver: Canvas ref is null'); + return; + } const ctx = canvas.getContext('2d'); - if (!ctx) return; + if (!ctx) { + console.error('Screensaver: Could not get 2D context'); + return; + } + + console.log('Screensaver: Canvas and context initialized'); // Set canvas size const resizeCanvas = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; + console.log('Screensaver: Canvas resized to', canvas.width, 'x', canvas.height); }; resizeCanvas(); @@ -175,6 +186,7 @@ export function Screensaver({ onClose }: ScreensaverProps) { // Get complementary colors const complementaryColors = getComplementaryColors(primaryColor); const colors = [primaryColor, ...complementaryColors]; + console.log('Screensaver: Using colors', colors); let startTime = Date.now(); let clearInterval = 0; @@ -209,9 +221,11 @@ export function Screensaver({ onClose }: ScreensaverProps) { animationRef.current = requestAnimationFrame(animate); }; + console.log('Screensaver: Starting animation'); animate(); return () => { + console.log('Screensaver: Cleaning up'); window.removeEventListener('resize', resizeCanvas); if (animationRef.current) { cancelAnimationFrame(animationRef.current); @@ -219,9 +233,24 @@ export function Screensaver({ onClose }: ScreensaverProps) { }; }, [primaryColor, lastClearTime]); - // Close on any key press or mouse movement + // Enable interaction detection after a delay to prevent immediate closing useEffect(() => { - const handleInteraction = () => onClose(); + const timer = setTimeout(() => { + console.log('Screensaver: Enabling interaction detection'); + setInteractionEnabled(true); + }, 1000); // 1 second delay + + return () => clearTimeout(timer); + }, []); + + // Close on any key press or mouse movement (only when interaction is enabled) + useEffect(() => { + if (!interactionEnabled) return; + + const handleInteraction = () => { + console.log('Screensaver: User interaction detected, closing'); + onClose(); + }; window.addEventListener('keydown', handleInteraction); window.addEventListener('mousemove', handleInteraction); @@ -234,7 +263,9 @@ export function Screensaver({ onClose }: ScreensaverProps) { window.removeEventListener('click', handleInteraction); window.removeEventListener('touchstart', handleInteraction); }; - }, [onClose]); + }, [onClose, interactionEnabled]); + + console.log('Screensaver: Rendering component'); return ( { - setScreensaverOpen(true); + console.log('ScreensaverButton: Opening manual screensaver'); + setManualScreensaverOpen(true); }; const handleCloseScreensaver = () => { - setScreensaverOpen(false); + console.log('ScreensaverButton: Closing screensaver'); + setManualScreensaverOpen(false); + resetTimer(); // Reset the auto-screensaver timer when manually closed }; + const isScreensaverOpen = manualScreensaverOpen || autoScreensaverActive; + + console.log('ScreensaverButton: Rendering, screensaverOpen =', isScreensaverOpen, 'autoActive =', autoScreensaverActive); + return ( <> @@ -21,7 +30,7 @@ export function ScreensaverButton() { - {screensaverOpen && ( + {isScreensaverOpen && ( )} diff --git a/client/src/hooks/useAutoScreensaver.ts b/client/src/hooks/useAutoScreensaver.ts new file mode 100644 index 0000000..e07041e --- /dev/null +++ b/client/src/hooks/useAutoScreensaver.ts @@ -0,0 +1,64 @@ +import { useState, useEffect, useCallback } from 'react'; + +export function useAutoScreensaver(timeoutMinutes: number = 5) { + const [isActive, setIsActive] = useState(false); + const [lastActivity, setLastActivity] = useState(Date.now()); + + const resetTimer = useCallback(() => { + setLastActivity(Date.now()); + if (isActive) { + setIsActive(false); + } + }, [isActive]); + + const activateScreensaver = useCallback(() => { + setIsActive(true); + }, []); + + // Track user activity + useEffect(() => { + const handleActivity = () => { + resetTimer(); + }; + + // Listen for various user activities + window.addEventListener('mousemove', handleActivity); + window.addEventListener('mousedown', handleActivity); + window.addEventListener('keydown', handleActivity); + window.addEventListener('touchstart', handleActivity); + window.addEventListener('scroll', handleActivity); + window.addEventListener('click', handleActivity); + + return () => { + window.removeEventListener('mousemove', handleActivity); + window.removeEventListener('mousedown', handleActivity); + window.removeEventListener('keydown', handleActivity); + window.removeEventListener('touchstart', handleActivity); + window.removeEventListener('scroll', handleActivity); + window.removeEventListener('click', handleActivity); + }; + }, [resetTimer]); + + // Check for timeout + useEffect(() => { + const timeoutMs = timeoutMinutes * 60 * 1000; + + const checkTimeout = () => { + const now = Date.now(); + if (now - lastActivity > timeoutMs && !isActive) { + console.log(`Auto-screensaver: Activating after ${timeoutMinutes} minutes of inactivity`); + activateScreensaver(); + } + }; + + const interval = setInterval(checkTimeout, 1000); // Check every second + + return () => clearInterval(interval); + }, [lastActivity, isActive, timeoutMinutes, activateScreensaver]); + + return { + isActive, + activateScreensaver, + resetTimer, + }; +} \ No newline at end of file