diff --git a/package-lock.json b/package-lock.json index 0edea08..4d9f1dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.22.0", - "tailwind-merge": "^2.2.1" + "tailwind-merge": "^2.2.1", + "zustand": "5.0.3" }, "devDependencies": { "@cloudflare/workers-types": "4.20250129.0", @@ -25,8 +26,8 @@ "@testing-library/react": "^14.2.1", "@testing-library/user-event": "^14.5.2", "@types/node": "20.17.16", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", + "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react-swc": "^3.5.0", @@ -10701,6 +10702,35 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zustand": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", + "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 5c566ef..47ef2d0 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.22.0", - "tailwind-merge": "^2.2.1" + "tailwind-merge": "^2.2.1", + "zustand": "5.0.3" }, "devDependencies": { "@cloudflare/workers-types": "4.20250129.0", @@ -39,8 +40,8 @@ "@testing-library/react": "^14.2.1", "@testing-library/user-event": "^14.5.2", "@types/node": "20.17.16", - "@types/react": "^18.2.55", - "@types/react-dom": "^18.2.19", + "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react-swc": "^3.5.0", diff --git a/src/App.tsx b/src/App.tsx index a8f3bcf..8a18c84 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import AboutPage from "@/pages/AboutPage"; import ProjectsPage from "@/pages/ProjectsPage"; import APCSPPage from "@/pages/APCSPPage"; import ParallaxPage from "@/pages/ParallaxPage"; +import VNCViewer from '@/components/VNCViewer'; const App = () => { return ( @@ -28,7 +29,8 @@ const App = () => { } /> } /> } /> - } /> + {/* } /> */} + } />

404: Page Not Found

diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 99479ce..d9191e0 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -32,6 +32,14 @@ const Navbar = () => { APCSP + + + noVNC + + { + const [isFullscreen, setIsFullscreen] = useState(false); const [isConnected, setIsConnected] = useState(false); - // Matrix rain effect characters - const chars = '01'; - const [drops, setDrops] = useState([]); - - useEffect(() => { - // Initialize matrix rain - const canvas = document.getElementById('matrix-bg'); - const ctx = canvas.getContext('2d'); - - canvas.width = window.innerWidth; - canvas.height = window.innerHeight; - - const fontSize = 10; - const columns = canvas.width / fontSize; - - const initialDrops = Array(Math.floor(columns)).fill(1); - setDrops(initialDrops); - - const draw = () => { - ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - ctx.fillStyle = '#0F0'; - ctx.font = fontSize + 'px monospace'; - - for (let i = 0; i < drops.length; i++) { - const text = chars.charAt(Math.floor(Math.random() * chars.length)); - ctx.fillText(text, i * fontSize, drops[i] * fontSize); - - if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) { - drops[i] = 0; - } - drops[i]++; + const toggleFullscreen = () => { + const iframe = document.getElementById('vnc-iframe'); + if (iframe) { + if (!document.fullscreenElement) { + iframe.requestFullscreen(); + setIsFullscreen(true); + } else { + document.exitFullscreen(); + setIsFullscreen(false); } - }; - - const interval = setInterval(draw, 33); - return () => clearInterval(interval); - }, []); + } + }; return ( -
- - -
-
- -

Raspberry Pi VNC Viewer

+
+
+ {/* Header */} +
+
+ +

Raspberry Pi Remote Access

+
+ +
+ + +
-
+ {/* VNC Viewer */} +
{isConnected ? ( -