diff --git a/client/src/components/Screensaver.tsx b/client/src/components/Screensaver.tsx index e24acfb..1e73eb8 100644 --- a/client/src/components/Screensaver.tsx +++ b/client/src/components/Screensaver.tsx @@ -33,6 +33,84 @@ function getComplementaryColors(primaryColor: string): string[] { return complementaryIndices.map(index => colorPalette[index]); } +// Check if current time is in night hours (midnight to 6am) +function isNightTime(): boolean { + const hour = new Date().getHours(); + return hour >= 0 && hour < 6; +} + +// Get fade opacity based on time (0 = full fade, 1 = no fade) +function getNightFadeOpacity(): number { + if (!isNightTime()) return 1; + + const hour = new Date().getHours(); + const minute = new Date().getMinutes(); + + // Calculate fade based on how far into the night we are + // Start fading at midnight (0), reach max fade at 3am, then fade back until 6am + const totalMinutes = hour * 60 + minute; + const maxFadeAt = 3 * 60; // 3am in minutes + + if (totalMinutes <= maxFadeAt) { + // Fading in: 0 to 3am + return Math.max(0.1, 1 - (totalMinutes / maxFadeAt) * 0.9); + } else { + // Fading out: 3am to 6am + const fadeOutMinutes = totalMinutes - maxFadeAt; + const fadeOutDuration = 3 * 60; // 3 hours + return Math.max(0.1, 0.1 + (fadeOutMinutes / fadeOutDuration) * 0.9); + } +} + +// Draw 24-hour clock +function drawClock( + ctx: CanvasRenderingContext2D, + width: number, + height: number +) { + const now = new Date(); + const hours = now.getHours().toString().padStart(2, '0'); + const minutes = now.getMinutes().toString().padStart(2, '0'); + const seconds = now.getSeconds().toString().padStart(2, '0'); + const timeString = `${hours}:${minutes}:${seconds}`; + + // Position clock in center + const centerX = width / 2; + const centerY = height / 2; + + // Draw clock background + ctx.save(); + ctx.globalAlpha = 0.3; + ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; + ctx.fillRect(centerX - 120, centerY - 60, 240, 120); + ctx.restore(); + + // Draw time text + ctx.save(); + ctx.fillStyle = 'white'; + ctx.font = 'bold 48px monospace'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(timeString, centerX, centerY); + ctx.restore(); + + // Draw date + const dateString = now.toLocaleDateString('en-US', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' + }); + + ctx.save(); + ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'; + ctx.font = '16px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(dateString, centerX, centerY + 50); + ctx.restore(); +} + // Create gradient pattern function createGradientPattern( ctx: CanvasRenderingContext2D, @@ -217,6 +295,19 @@ export function Screensaver({ onClose }: ScreensaverProps) { // Draw line art drawLineArt(ctx, canvas.width, canvas.height, colors, elapsed); + // Apply night fade if needed + const nightFadeOpacity = getNightFadeOpacity(); + if (nightFadeOpacity < 1) { + ctx.save(); + ctx.globalAlpha = 1 - nightFadeOpacity; + ctx.fillStyle = 'black'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.restore(); + } + + // Draw clock + drawClock(ctx, canvas.width, canvas.height); + clearInterval += 16; // ~60fps animationRef.current = requestAnimationFrame(animate); };