import { useEffect, useState } from 'react'; import { supabase } from './supabaseClient'; import Auth from './components/Auth'; import ReviewQueue from './components/ReviewQueue'; import JourneyPath from './components/JourneyPath'; import WindowShell from './components/WindowShell'; import TerminalEmulator from './components/TerminalEmulator'; import PythonChallenge from './components/PythonChallenge'; import MySQLPlayground from './components/MySQLPlayground'; import FileExplorer from './components/FileExplorer'; import Settings from './components/Settings'; interface WindowState { isOpen: boolean; isMinimized: boolean; } export default function App() { const [user, setUser] = useState(null); const [overrideProblemId, setOverrideProblemId] = useState(null); // Window states const [windows, setWindows] = useState>({ queue: { isOpen: true, isMinimized: false }, journey: { isOpen: false, isMinimized: false }, terminal: { isOpen: false, isMinimized: false }, computer: { isOpen: false, isMinimized: false }, sync: { isOpen: false, isMinimized: false }, python: { isOpen: false, isMinimized: false }, mysql: { isOpen: false, isMinimized: false }, settings: { isOpen: false, isMinimized: false }, }); const [activeWindow, setActiveWindow] = useState('queue'); const [isMobile, setIsMobile] = useState(false); // Start Menu and System info const [isStartOpen, setIsStartOpen] = useState(false); const [streak, setStreak] = useState(null); const [time, setTime] = useState(''); // Sync state const [syncing, setSyncing] = useState(false); const [syncResult, setSyncResult] = useState(null); // Wallpaper state const [wallpaperUrl, setWallpaperUrl] = useState(() => { return localStorage.getItem('desktopWallpaperUrl') || 'https://lh3.googleusercontent.com/aida-public/AB6AXuAMJHVhhK8_G7F8sbhn8F7w4AZWXb1O_-HLKvrZ_fJlbUVMcVuxxEOO_LlOh8qIwtAn2KvzvCwzmtNLLEZ5uYkCEsx8ZWXJR609qgSMRSX8LBBeskk4VzVXnyzsgIKCedeV2PvGxJlUNnledcWKCXqG9egQi8dgTcA7C2z82QyM73KZ4s7ZRzZHNupuQt1ocfcMl9E_x1PWFRridl751LIpyGZgednS5CmVw2rZvFc_tbp2QTxgVHJ_59myEBmy6aajbO06AhkKmCvI'; }); // Context menu state const [contextMenu, setContextMenu] = useState<{ visible: boolean; x: number; y: number }>({ visible: false, x: 0, y: 0 }); // Fullscreen state const [isFullscreen, setIsFullscreen] = useState(false); // Fetch streak info const fetchStreak = async () => { try { const { data: { session } } = await supabase.auth.getSession(); if (!session) return; const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/streak`, { headers: { 'Authorization': `Bearer ${session.access_token}` } }); if (res.ok) { const data = await res.json(); setStreak(data); } } catch (err) { console.error('Error fetching streak:', err); } }; useEffect(() => { // Check initial session supabase.auth.getSession().then(({ data: { session } }) => { setUser(session?.user ?? null); }); // Listen for auth state changes const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => { setUser(session?.user ?? null); }); // Clock Updater const updateTime = () => { const date = new Date(); let hours = date.getHours(); const minutes = date.getMinutes(); const ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; // 0 is 12 const minStr = minutes < 10 ? '0' + minutes : minutes; setTime(`${hours}:${minStr} ${ampm}`); }; updateTime(); const interval = setInterval(updateTime, 30000); return () => { subscription.unsubscribe(); clearInterval(interval); }; }, []); useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth < 768); }; checkMobile(); window.addEventListener('resize', checkMobile); return () => { window.removeEventListener('resize', checkMobile); }; }, []); useEffect(() => { if (user) { fetchStreak(); const savedWallpaper = localStorage.getItem('desktopWallpaperUrl'); if (savedWallpaper) { setWallpaperUrl(savedWallpaper); } } }, [user]); // Fullscreen change listener useEffect(() => { const handleFullscreenChange = () => { setIsFullscreen(!!document.fullscreenElement); }; document.addEventListener('fullscreenchange', handleFullscreenChange); return () => { document.removeEventListener('fullscreenchange', handleFullscreenChange); }; }, []); // Zoom prevention listener useEffect(() => { const handleWheel = (e: WheelEvent) => { if (e.ctrlKey) { e.preventDefault(); } }; const handleKeydown = (e: KeyboardEvent) => { if (e.ctrlKey && ( e.key === '=' || e.key === '-' || e.key === '0' || e.key === '+' || e.code === 'NumpadAdd' || e.code === 'NumpadSubtract' )) { e.preventDefault(); } }; const handleTouchmove = (e: TouchEvent) => { if (e.touches.length > 1) { e.preventDefault(); } }; document.addEventListener('wheel', handleWheel, { passive: false }); document.addEventListener('keydown', handleKeydown); document.addEventListener('touchmove', handleTouchmove, { passive: false }); return () => { document.removeEventListener('wheel', handleWheel); document.removeEventListener('keydown', handleKeydown); document.removeEventListener('touchmove', handleTouchmove); }; }, []); const handleContextMenu = (e: React.MouseEvent) => { const target = e.target as HTMLElement; // Prevent menu if clicking interactive windows/buttons/inputs if ( target.closest('.window-shadow') || target.closest('button') || target.closest('input') || target.closest('textarea') || target.closest('details') || target.closest('#start-menu') ) { return; } e.preventDefault(); setContextMenu({ visible: true, x: e.clientX, y: e.clientY }); }; const closeContextMenu = () => { if (contextMenu.visible) { setContextMenu(prev => ({ ...prev, visible: false })); } }; const toggleFullscreen = () => { closeContextMenu(); if (!document.fullscreenElement) { document.documentElement.requestFullscreen().catch((err) => { console.error(`Error enabling fullscreen: ${err.message}`); }); } else { document.exitFullscreen(); } }; const compressAndSaveWallpaper = (file: File) => { const reader = new FileReader(); reader.onload = (event) => { const img = new Image(); img.onload = () => { const canvas = document.createElement('canvas'); let width = img.width; let height = img.height; const MAX_WIDTH = 1920; const MAX_HEIGHT = 1080; if (width > MAX_WIDTH || height > MAX_HEIGHT) { if (width / height > MAX_WIDTH / MAX_HEIGHT) { height = Math.round((height * MAX_WIDTH) / width); width = MAX_WIDTH; } else { width = Math.round((width * MAX_HEIGHT) / height); height = MAX_HEIGHT; } } canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); if (ctx) { ctx.drawImage(img, 0, 0, width, height); try { const dataUrl = canvas.toDataURL('image/jpeg', 0.7); setWallpaperUrl(dataUrl); localStorage.setItem('desktopWallpaperUrl', dataUrl); localStorage.setItem('customWallpaperUrl', dataUrl); localStorage.setItem('customWallpaperName', file.name); } catch (err) { console.error('Failed to save compressed image to localStorage:', err); // Fallback: set it as state but warn const rawDataUrl = event.target?.result as string; setWallpaperUrl(rawDataUrl); } } else { const rawDataUrl = event.target?.result as string; setWallpaperUrl(rawDataUrl); try { localStorage.setItem('desktopWallpaperUrl', rawDataUrl); localStorage.setItem('customWallpaperUrl', rawDataUrl); localStorage.setItem('customWallpaperName', file.name); } catch (err) { console.error('Failed to save raw image to localStorage:', err); } } }; img.src = event.target?.result as string; }; reader.readAsDataURL(file); }; const handleWallpaperChange = (e: React.ChangeEvent) => { closeContextMenu(); const file = e.target.files?.[0]; if (file) { compressAndSaveWallpaper(file); } }; const openWindow = (id: string) => { setWindows(prev => ({ ...prev, [id]: { isOpen: true, isMinimized: false } })); setActiveWindow(id); setIsStartOpen(false); }; const closeWindow = (id: string) => { setWindows(prev => ({ ...prev, [id]: { ...prev[id], isOpen: false } })); }; const minimizeWindow = (id: string) => { setWindows(prev => ({ ...prev, [id]: { ...prev[id], isMinimized: true } })); }; const toggleWindowMinimize = (id: string) => { setWindows(prev => { const win = prev[id]; if (win.isMinimized || !win.isOpen) { setActiveWindow(id); return { ...prev, [id]: { isOpen: true, isMinimized: false } }; } else if (activeWindow === id) { return { ...prev, [id]: { ...win, isMinimized: true } }; } else { setActiveWindow(id); return prev; } }); }; const handleSelectProblemForReview = (problemId: string) => { setOverrideProblemId(problemId); openWindow('queue'); }; const triggerSync = async () => { openWindow('sync'); setSyncing(true); setSyncResult(null); try { const { data: { session } } = await supabase.auth.getSession(); if (!session) return; const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/sync`, { method: 'POST', headers: { 'Authorization': `Bearer ${session.access_token}` } }); if (res.ok) { const data = await res.json(); setSyncResult(data.message || 'Synchronization successfully completed!'); fetchStreak(); } else { setSyncResult('Sync operation failed at server host.'); } } catch { setSyncResult('Cloud synchronization server unreachable.'); } finally { setSyncing(false); } }; const handleSignOut = async () => { setIsStartOpen(false); await supabase.auth.signOut(); }; if (!user) { return ; } const username = user.email ? user.email.split('@')[0] : 'Player_One'; const isAnyWindowOpen = Object.values(windows).some(w => w.isOpen && !w.isMinimized); return (
{/* Background Wallpaper image */}
{/* Desktop Icons column */} {!isMobile && ( )} {/* System Gadget Widget (Top Right) */} {!isMobile && (
Profile.sys
{username}
local_fire_department {streak?.current_streak ?? 0} DAY STREAK
)} {/* Windows Phone Metro Start Screen (Mobile Home View) */} {isMobile && !isAnyWindowOpen && (
{/* Metro Header */}
AlgoSpaced OS v1.0

start

{/* Tiles Grid */}
{/* Profile Tile (Wide - 2 cols) */}
{username}
local_fire_department {streak?.current_streak ?? 0} DAY STREAK
{/* Daily Queue Tile */} {/* Journey Path Tile */} {/* My Computer Tile */} {/* Terminal Tile */} {/* Python Challenge Tile */} {/* MySQL Playground Tile */} {localStorage.getItem('algospaced_sandbox_mode') === 'true' && ( )} {/* Drive Sync Tile (Wide - 2 cols) */}
)} {/* Floating Windows Shell Containers */} {/* 1. Daily Review Queue Window */} closeWindow('queue')} onMinimize={() => minimizeWindow('queue')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="750px" defaultHeight="600px" isMobile={isMobile} > setOverrideProblemId(null)} /> {/* 2. Journey Path Map Window */} closeWindow('journey')} onMinimize={() => minimizeWindow('journey')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="700px" defaultHeight="560px" isMobile={isMobile} > {/* 3. Command Line Terminal Window */} closeWindow('terminal')} onMinimize={() => minimizeWindow('terminal')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="640px" defaultHeight="450px" titleBarColor="#1e293b" isMobile={isMobile} > closeWindow('terminal')} /> {/* 4. Google Drive Sync Dialog Window */} closeWindow('sync')} onMinimize={() => minimizeWindow('sync')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="480px" defaultHeight="320px" titleBarColor="#855400" isMobile={isMobile} >
cloud_sync

DRIVE NOTES SYNCHRONIZATION

Importing LeetCode sheets
{syncing ? (
SYNC PROCESS RUNNING...

Connecting to Supabase partition, requesting Google Drive manifest, indexing note items...

) : (
{syncResult || 'Idle. Ready to synchronize Leitner box data logs from Sheets drive storage.'}
)}
{/* 5. My Computer Window (Interactive File Explorer) */} closeWindow('computer')} onMinimize={() => minimizeWindow('computer')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="640px" defaultHeight="480px" titleBarColor="#006686" isMobile={isMobile} > {/* 6. Daily Python Challenge Window */} closeWindow('python')} onMinimize={() => minimizeWindow('python')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="620px" defaultHeight="580px" titleBarColor="#9d4edd" isMobile={isMobile} > {/* 7. MySQL Playground Window */} closeWindow('mysql')} onMinimize={() => minimizeWindow('mysql')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="660px" defaultHeight="580px" titleBarColor="#0ea5e9" isMobile={isMobile} > {/* 8. API Control Panel Window */} closeWindow('settings')} onMinimize={() => minimizeWindow('settings')} activeWindow={activeWindow} setActiveWindow={setActiveWindow} defaultWidth="500px" defaultHeight="450px" titleBarColor="#10b981" isMobile={isMobile} > {/* Start Menu Popup */} {isStartOpen && (
e.stopPropagation()} className="absolute bottom-14 left-0 w-64 bg-white border-[3px] border-ink-black shadow-[6px_6px_0px_0px_#1E293B] flex flex-col p-4 z-[60] ml-2 mb-2 select-none" >
{localStorage.getItem('algospaced_sandbox_mode') === 'true' && ( )}
)} {/* Taskbar Bottom (Taskbar fixed layout) */}
setIsStartOpen(false)} className="fixed bottom-0 left-0 w-full z-50 flex items-center justify-between h-14 border-t-[4px] border-ink-black bg-[#0ea5e9] px-0 select-none shadow-[0_-4px_0_0_rgba(30,41,59,0.1)]" >
{/* Start button */} {/* Windows tabs in taskbar */} {/* Daily Queue Tab */} {windows.queue.isOpen && ( )} {/* Journey Path Tab */} {windows.journey.isOpen && ( )} {/* Terminal Tab */} {windows.terminal.isOpen && ( )} {/* Google Drive Sync Tab */} {windows.sync.isOpen && ( )} {/* My Computer Tab */} {windows.computer.isOpen && ( )} {/* Python Challenge Tab */} {windows.python.isOpen && ( )} {/* MySQL Playground Tab */} {windows.mysql.isOpen && ( )} {/* API Settings Tab */} {windows.settings?.isOpen && ( )}
{/* System tray (wifi, clock, volume) */}
volume_up network_wifi
{time}
{/* Context Menu (Right Click Options) */} {contextMenu.visible && (
)} {/* Hidden Wallpaper File Input Selector */}
); }