ada-web

Ada AI is a specialized coding...
Log | Files | Refs | README | LICENSE

commit 91fad622961760a8a95c69db7507da3aa3cb39d3
parent 537fa8d0a39d1911ac9f187ed876db28e7b7cc9a
Author: Amit Dutta <amitdutta4255@gmail.com>
Date:   Wed, 21 Jan 2026 21:01:20 +0530

Ui update

Diffstat:
Mdocs/404.html | 347++++++++++++++++++++++++++++++++-----------------------------------------------
Adocs/c.html | 1147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/cpp.html | 1011+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdocs/docs.html | 694+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mdocs/index.html | 1832++++++++++++-------------------------------------------------------------------
Mdocs/logo.png | 0
Adocs/python.html | 1028+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdocs/sitemap.xml | 19++++++++++++-------
8 files changed, 4100 insertions(+), 1978 deletions(-)

diff --git a/docs/404.html b/docs/404.html @@ -1,220 +1,149 @@ <!DOCTYPE html> <html lang="en"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>404 Page Not Found</title> - <style> - body { - margin: 0; - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - background-color: #f0f2f5; - font-family: 'Arial', sans-serif; - overflow: hidden; /* Prevent scrollbars from animation */ - } - - .container { - text-align: center; - padding: 20px; - background: #fff; - border-radius: 10px; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - position: relative; - overflow: hidden; - max-width: 90%; - } - - .boy-container { - position: relative; - width: 200px; /* Adjust size as needed */ - height: 250px; /* Adjust size as needed */ - margin: 0 auto 20px; - overflow: hidden; - } - - .boy { - width: 100%; - height: 100%; - position: absolute; - bottom: 0; - left: 0; - animation: cry 1.5s infinite alternate; - display: flex; - justify-content: center; - align-items: flex-start; - padding-top: 30px; - box-sizing: border-box; - } - - /* SVG styles for the boy */ - .boy-svg { - width: 100%; - height: 100%; - position: absolute; - bottom: 0; - left: 0; - } - - .boy-head { - fill: #add8e6; /* Skin color */ - } - - .boy-body { - fill: #87ceeb; /* Shirt color */ - } - - .boy-arm { - fill: #add8e6; /* Skin color */ - } - - .tear { - width: 5px; - height: 15px; - background-color: #4682b4; /* Blue for tears */ - border-radius: 50%; - position: absolute; - top: 70px; /* Adjust tear position */ - animation: fallTear 1s infinite; - opacity: 0; - } - - .tear.left { - left: 60px; - animation-delay: 0.2s; - } - - .tear.right { - right: 60px; - animation-delay: 0.5s; - } - - .board { - position: absolute; - width: 150px; - height: 80px; - background-color: #8b4513; /* Wood color */ - border: 2px solid #5a2c00; - border-radius: 5px; - color: #fff; - display: flex; - justify-content: center; - align-items: center; - font-size: 1.2em; - font-weight: bold; - text-align: center; - bottom: 50px; /* Initial position relative to the boy */ - left: 50%; - transform: translateX(-50%); - transform-origin: bottom center; - animation: holdBoard 0s forwards; /* Initial state, controlled by JS */ - box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); - } - - h1 { - color: #333; - font-size: 3em; - margin-bottom: 10px; - } - - p { - color: #666; - font-size: 1.2em; - margin-bottom: 30px; - } - a { - display: inline-block; - padding: 10px 20px; - background-color: #007bff; - color: #fff; - text-decoration: none; - border-radius: 5px; - transition: background-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease; /* Added transform and box-shadow to transition */ - box-shadow: 0 2px 5px rgba(0, 123, 255, 0.2); /* Initial shadow */ - } - - a:hover { - background-color: #0056b3; - transform: translateY(-3px) scale(1.05); /* Lift and slightly enlarge on hover */ - box-shadow: 0 5px 15px rgba(0, 123, 255, 0.4); /* More prominent shadow on hover */ - } - - /* Animations */ - @keyframes cry { - 0% { transform: translateY(0); } - 100% { transform: translateY(-5px); } - } - - @keyframes fallTear { - 0% { transform: translateY(0); opacity: 1; } - 100% { transform: translateY(30px); opacity: 0; } - } - - @keyframes boardFall { - 0% { transform: translate(-50%, 0) rotate(0deg); opacity: 1; } - 100% { transform: translate(-50%, 150px) rotate(45deg); opacity: 0; } - } - - @keyframes boardPickUp { - 0% { transform: translate(-50%, 150px) rotate(45deg); opacity: 0; } - 50% { transform: translate(-50%, 50px) rotate(-10deg); opacity: 1; } - 100% { transform: translate(-50%, 0) rotate(0deg); opacity: 1; } - } - - @keyframes boardHold { - 0% { transform: translate(-50%, 0) rotate(0deg); opacity: 1; } - 50% { transform: translate(-50%, 5px) rotate(2deg); } - 100% { transform: translate(-50%, 0) rotate(0deg); } - } - </style> +<head> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css'> +<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Arvo'> + <!-- The font was updated to 'Inter' as requested. --> +<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> </head> -<body> - <div class="container"> - <div class="boy-container"> - <div class="boy"> - <!-- Simple SVG for the boy --> - <svg class="boy-svg" viewBox="0 0 200 250" preserveAspectRatio="xMidYMid meet"> - <circle class="boy-head" cx="100" cy="70" r="50"/> - <rect class="boy-body" x="60" y="120" width="80" height="130" rx="20" ry="20"/> - <!-- Arms (simplified) --> - <rect class="boy-arm" x="40" y="130" width="20" height="80" rx="10" ry="10" transform="rotate(-10 50 170)"/> - <rect class="boy-arm" x="140" y="130" width="20" height="80" rx="10" ry="10" transform="rotate(10 150 170)"/> - </svg> - <div class="tear left"></div> - <div class="tear right"></div> - </div> - <div class="board" id="board">Page Not Found</div> - </div> - <h1>404</h1> - <p>Oops! The page you're looking for doesn't exist.</p> - <a href="/">Go to Homepage</a> - </div> - <script> - const board = document.getElementById('board'); - const boy = document.querySelector('.boy'); +<style> + body{ + margin:0; + padding:0; + font-family: 'Inter', sans-serif; + height:100vh; +background-image: linear-gradient(to top, #2e1753, #1f1746, #131537, #0d1028, #050819); + display:flex; + justify-content:center; + align-items:center; + overflow:hidden; +} +.text{ + position:absolute; + top:10%; + color:#fff; + text-align:center; +} +h1{ + font-size:50px; +} +.star{ + position:absolute; + width:2px; + height:2px; + background:#fff; + right:0; + animation:starTwinkle 3s infinite linear; +} +.astronaut img{ + width:100px; + position:absolute; + top:55%; + animation:astronautFly 6s infinite linear; +} +@keyframes astronautFly{ + 0%{ + left:-100px; + } + 25%{ + top:50%; + transform:rotate(30deg); + } + 50%{ + transform:rotate(45deg); + top:55%; + } + 75%{ + top:60%; + transform:rotate(30deg); + } + 100%{ + left:110%; + transform:rotate(45deg); + } +} +@keyframes starTwinkle{ + 0%{ + background:rgba(255,255,255,0.4); + } + 25%{ + background:rgba(255,255,255,0.8); + } + 50%{ + background:rgba(255,255,255,1); + } + 75%{ + background:rgba(255,255,255,0.8); + } + 100%{ + background:rgba(255,255,255,0.4); + } +} + + + +@media (max-width: 768px) { + .four_zero_four_bg { + height: 200px; + } + .four_zero_four_bg h1 { + font-size: 40px; + } + .four_zero_four_bg h3 { + font-size: 40px; + } + .button a { + font-size: 16px; + padding: 15px 30px; + } +} +</style> - function animateBoard() { - // Board falls - board.style.animation = 'boardFall 1s forwards'; +<body> - setTimeout(() => { - // Board picks up and holds - board.style.animation = 'boardPickUp 1.5s forwards, boardHold 3s 1.5s infinite linear'; - board.style.opacity = '1'; // Ensure it's visible after picking up + <div class="text"> + <div>ERROR</div> + <h1>404</h1> + <hr> + <div>Page Not Found</div><br> + <div><a href="https://compiler.aranag.site" style="color: #fff; text-decoration: none;"><u>Go to Homepage</u></a></div> +</div> - // Restart the loop after a delay - setTimeout(() => { - animateBoard(); - }, 3000); // Adjust this delay to control loop speed - }, 1000); // Delay before picking up starts - } +<div class="astronaut"> + <img src="https://images.vexels.com/media/users/3/152639/isolated/preview/506b575739e90613428cdb399175e2c8-space-astronaut-cartoon-by-vexels.png" alt="" class="src"> +</div> - // Initial call to start the animation loop - animateBoard(); - </script> + </div> + </div> + </div> + </div> + </div> +</section> </body> +<script> + document.addEventListener("DOMContentLoaded",function(){ + + var body=document.body; + setInterval(createStar,100); + function createStar(){ + var right=Math.random()*500; + var top=Math.random()*screen.height; + var star=document.createElement("div"); + star.classList.add("star") + body.appendChild(star); + setInterval(runStar,10); + star.style.top=top+"px"; + function runStar(){ + if(right>=screen.width){ + star.remove(); + } + right+=3; + star.style.right=right+"px"; + } + } +}) +</script> </html> diff --git a/docs/c.html b/docs/c.html @@ -0,0 +1,1146 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + <title>Amit Dutta // C Compiler</title> + <link rel="icon" type="image/x-icon" href="https://compiler.aranag.site/logo.png"> + + <!-- Fonts & Icons --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> + + <!-- Tailwind CSS --> + <script src="https://cdn.tailwindcss.com"></script> + + <!-- CodeMirror 5 (Professional Editor) --> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/clike/clike.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/closebrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/matchbrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/selection/active-line.min.js"></script> + + <!-- Xterm.js --> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" /> + <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script> + <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script> + + <!-- LZ-String Compression --> + <script src="https://cdn.jsdelivr.net/npm/lz-string@1.5.0/libs/lz-string.min.js"></script> + + <style> + :root { + --bg-main: #050505; + --accent: #bef264; /* Lime 300 */ + --text-muted: #737373; + --border-color: rgba(255, 255, 255, 0.1); + } + + body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-main); + color: #f5f5f5; + height: 100vh; + height: 100dvh; + overflow: hidden; + display: flex; + flex-direction: column; + } + + /* Portfolio Aesthetic */ + .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-heading { font-family: 'Space Grotesk', sans-serif; } + + /* Noise Overlay */ + .bg-noise { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; z-index: 0; opacity: 0.03; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + } + + /* CRT Scanline */ + .crt-scanline { + position: fixed; top: 0; left: 0; width: 100%; height: 2px; + background: rgba(190, 242, 100, 0.1); opacity: 0.5; + pointer-events: none; z-index: 50; + animation: scanline 8s linear infinite; + } + @keyframes scanline { 0% { top: -10vh; } 100% { top: 110vh; } } + + /* CodeMirror Customization */ + .CodeMirror { + height: 100% !important; + font-family: 'JetBrains Mono', monospace; + font-size: 13px; + background-color: #0c0f16 !important; /* Slightly lighter than pure black */ + color: #f8f8f2; + } + .CodeMirror-gutters { + background-color: #0c0f16 !important; + border-right: 1px solid rgba(255,255,255,0.05) !important; + } + .CodeMirror-linenumber { + color: #555 !important; + } + .CodeMirror-cursor { + border-left: 2px solid var(--accent) !important; + } + .CodeMirror-selected { + background: rgba(190, 242, 100, 0.2) !important; + } + .cm-s-dracula .CodeMirror-activeline-background { + background: rgba(255, 255, 255, 0.03) !important; + } + + /* Custom Scrollbar styling */ + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + ::-webkit-scrollbar-track { + background: #0c0f16; + } + ::-webkit-scrollbar-thumb { + background: #333; + border-radius: 4px; + border: 2px solid #0c0f16; /* Creates padding effect */ + } + ::-webkit-scrollbar-thumb:hover { + background: #bef264; /* Lime on hover */ + } + + /* Specifically for CodeMirror to ensure it takes the custom style */ + .CodeMirror-scroll::-webkit-scrollbar, + .xterm-viewport::-webkit-scrollbar { + width: 8px; + height: 8px; + } + .CodeMirror-scroll::-webkit-scrollbar-track, + .xterm-viewport::-webkit-scrollbar-track { + background: #050505; + } + .CodeMirror-scroll::-webkit-scrollbar-thumb, + .xterm-viewport::-webkit-scrollbar-thumb { + background: #2a2a2a; + border-radius: 4px; + border: 1px solid #050505; + } + .CodeMirror-scroll::-webkit-scrollbar-thumb:hover, + .xterm-viewport::-webkit-scrollbar-thumb:hover { + background: var(--accent); + } + + /* Mobile Helper Bar */ + #mobile-helper-bar { + display: none; /* Shown via JS on mobile */ + background: #151515; + border-top: 1px solid rgba(255,255,255,0.1); + padding: 8px; + overflow-x: auto; + white-space: nowrap; + -webkit-overflow-scrolling: touch; + } + @media (max-width: 768px) { + #mobile-helper-bar { display: flex; gap: 8px; } + } + .helper-key { + background: rgba(255,255,255,0.1); + color: var(--accent); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 4px; + padding: 6px 12px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + font-weight: bold; + cursor: pointer; + user-select: none; + } + .helper-key:active { background: var(--accent); color: black; } + + /* Toast Notification */ + .toast { + position: fixed; + bottom: 2rem; + left: 50%; + transform: translateX(-50%) translateY(100px); + background: #1a1a1a; + border: 1px solid var(--accent); + color: var(--accent); + padding: 0.5rem 1.5rem; + border-radius: 9999px; + font-family: 'JetBrains Mono', monospace; + font-size: 0.8rem; + transition: transform 0.3s ease; + z-index: 100; + } + .toast.show { transform: translateX(-50%) translateY(0); } + + /* Connection Dot Pulse */ + .pulse-dot { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); + animation: pulse-white 2s infinite; + } + .pulse-dot.connected { + background-color: #bef264; /* Lime */ + box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); + animation: pulse-lime 2s infinite; + } + .pulse-dot.disconnected { + background-color: #ef4444; /* Red */ + box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); + animation: pulse-red 2s infinite; + } + + @keyframes pulse-lime { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(190, 242, 100, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0); } + } + @keyframes pulse-red { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } + } + + /* AI Text Overlay */ + .ai-overlay { + position: absolute; + bottom: 10px; + right: 20px; + background: rgba(20, 20, 20, 0.9); + border: 1px solid #ef4444; + color: #fca5a5; + padding: 8px 12px; + border-radius: 6px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + z-index: 60; + display: none; + backdrop-filter: blur(4px); + animation: slideIn 0.3s ease-out; + box-shadow: 0 4px 12px rgba(0,0,0,0.5); + } + .ai-overlay.visible { display: flex; align-items: center; gap: 8px; } + + .ai-link { + color: #fff; + text-decoration: underline; + text-decoration-style: dotted; + text-underline-offset: 4px; + cursor: pointer; + font-weight: bold; + transition: color 0.2s; + } + .ai-link:hover { color: #bef264; text-decoration-style: solid; } + + @keyframes slideIn { + from { transform: translateY(20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } + } + + /* Modals (AI & Clear) */ + .modal-overlay { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.8); backdrop-filter: blur(5px); + z-index: 200; display: none; align-items: center; justify-content: center; + } + .modal-overlay.open { display: flex; } + + .modal-content { + background: #0f0f0f; + border: 1px solid var(--accent); + width: 90%; max-width: 600px; + border-radius: 12px; + display: flex; flex-direction: column; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + overflow: hidden; + animation: modalPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + } + + @keyframes modalPop { + 0% { transform: scale(0.9); opacity: 0; } + 100% { transform: scale(1); opacity: 1; } + } + + /* Editor Toolbar Buttons */ + .editor-btn { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + color: #737373; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s; + cursor: pointer; + } + .editor-btn:hover { + background: rgba(255,255,255,0.1); + color: #fff; + border-color: rgba(255,255,255,0.3); + } + .editor-btn.danger:hover { + background: rgba(239, 68, 68, 0.1); + color: #ef4444; + border-color: #ef4444; + } + + /* RESIZER STYLES */ + #resizer { + background-color: rgba(255,255,255,0.05); + cursor: col-resize; + transition: background-color 0.2s; + z-index: 50; + display: none; /* hidden on mobile */ + } + #resizer:hover, #resizer.resizing { + background-color: var(--accent); + } + @media (min-width: 768px) { + #resizer { + display: flex; + width: 8px; + align-items: center; + justify-content: center; + } + } + /* Prevent selection during drag */ + body.resizing { + user-select: none; + cursor: col-resize; + } + /* Cover iframes during drag to prevent event stealing */ + .iframe-shield { + position: absolute; + inset: 0; + z-index: 999; + display: none; + } + body.resizing .iframe-shield { + display: block; + } + </style> +</head> +<body class="antialiased selection:bg-lime-300 selection:text-black"> + + <div class="bg-noise"></div> + <div class="crt-scanline"></div> + <div id="toast" class="toast">Link Copied to Clipboard!</div> + + <!-- AI Overlay in Terminal --> + <div id="ai-suggestion" class="ai-overlay"> + <i class="fas fa-exclamation-triangle text-red-500"></i> + <span>Error detected. <span id="ask-ai-link" class="ai-link">Ask AI</span> to fix it.</span> + </div> + + <!-- Clear Confirmation Modal --> + <div id="clear-modal" class="modal-overlay"> + <div class="modal-content max-w-[320px] p-0 border-red-500/50"> + <div class="bg-red-500/10 px-6 py-4 border-b border-red-500/20"> + <h3 class="font-heading font-bold text-lg text-red-500 flex items-center gap-2"> + <i class="fas fa-exclamation-circle"></i> CLEAR CODE + </h3> + </div> + <div class="p-6 text-center"> + <p class="text-neutral-300 text-sm font-sans mb-6">Are you sure you want to clear the editor? This action will remove all current code.</p> + <div class="flex justify-center gap-3"> + <button id="cancel-clear-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all border border-transparent">Cancel</button> + <button id="confirm-clear-btn" class="bg-red-500/10 hover:bg-red-500 hover:text-black text-red-500 border border-red-500/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2"> + <i class="fas fa-trash-alt"></i> Confirm + </button> + </div> + </div> + </div> + </div> + + <!-- AI Fix Modal --> + <div id="ai-modal" class="modal-overlay"> + <div class="modal-content max-h-[80vh]"> + <!-- Modal Header --> + <div class="bg-white/5 px-6 py-4 border-b border-white/10 flex justify-between items-center"> + <h3 class="font-heading font-bold text-lg text-lime-300 flex items-center gap-2"> + <i class="fas fa-robot"></i> AI Diagnosis + </h3> + <button id="close-modal" class="text-neutral-500 hover:text-white transition-colors"> + <i class="fas fa-times"></i> + </button> + </div> + + <!-- Modal Body --> + <div class="p-6 overflow-y-auto custom-scrollbar flex-1"> + <div id="ai-loading" class="hidden flex flex-col items-center justify-center py-8 gap-4"> + <div class="pulse-dot connected" style="width: 12px; height: 12px;"></div> + <p class="font-mono text-neutral-400 text-sm animate-pulse">Analyzing compile error...</p> + </div> + + <div id="ai-result" class="hidden space-y-4"> + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Explanation</h4> + <p id="ai-explanation" class="text-sm text-neutral-200 leading-relaxed font-sans"></p> + </div> + + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Suggested Fix</h4> + <div class="relative group"> + <pre id="ai-code-preview" class="bg-black/30 border border-white/10 p-3 rounded text-xs font-mono text-lime-100 overflow-x-auto custom-scrollbar"></pre> + </div> + </div> + </div> + + <div id="ai-error-msg" class="hidden text-red-400 text-sm font-mono text-center py-4"></div> + </div> + + <!-- Modal Footer --> + <div class="bg-white/5 px-6 py-4 border-t border-white/10 flex justify-end gap-3"> + <button id="cancel-fix-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all">Dismiss</button> + <button id="apply-fix-btn" disabled class="bg-lime-300/10 hover:bg-lime-300 hover:text-black text-lime-300 border border-lime-300/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"> + <i class="fas fa-check"></i> Apply Fix + </button> + </div> + </div> + </div> + + <!-- Header (Responsive) --> + <header class="h-auto md:h-16 flex flex-col md:flex-row items-center justify-between px-4 py-3 md:px-6 shrink-0 border-b border-white/10 z-20 bg-neutral-900/50 backdrop-blur-md gap-3 md:gap-4"> + + <!-- Top Row: Title & Editor Tools --> + <div class="flex items-center justify-between w-full md:w-auto gap-6"> + <h1 class="text-lg md:text-xl font-heading font-bold text-white tracking-tight flex items-center"> + <span class="text-lime-300 mr-2">//</span>C.COMPILER + <span id="conn-dot" class="pulse-dot disconnected ml-3" title="Disconnected"></span> + </h1> + + <!-- Editor Tools --> + <div class="flex items-center gap-2"> + <button id="undo-btn" class="editor-btn" title="Undo (Ctrl+Z)"> + <i class="fas fa-undo text-xs"></i> + </button> + <button id="redo-btn" class="editor-btn" title="Redo (Ctrl+Y)"> + <i class="fas fa-redo text-xs"></i> + </button> + <div class="w-px h-4 bg-white/10 mx-1"></div> + <button id="clear-code-btn" class="editor-btn danger" title="Clear Code"> + <i class="fas fa-times text-xs"></i> + </button> + </div> + + <!-- Mobile Only: Exit Link --> + <a href="./index.html" class="md:hidden font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors ml-auto">[ EXIT ]</a> + </div> + + <!-- Middle: Connection Text --> + <div class="hidden md:flex items-center gap-2 font-mono text-xs text-neutral-500"> + <span id="connection-status">Connecting to server...</span> + </div> + + <!-- Bottom/Right: Buttons --> + <div class="flex items-center gap-2 w-full md:w-auto justify-end"> + <a href="./index.html" class="hidden md:inline font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors mr-2">[ EXIT ]</a> + + <button id="download-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Download .c"> + <i class="fas fa-download"></i> + </button> + + <button id="reset-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Reset Terminal"> + <i class="fas fa-rotate-left"></i> + </button> + + <button id="share-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Share Code"> + <i class="fas fa-share-alt"></i> + </button> + + <button id="run-btn" disabled class="bg-white/5 hover:bg-lime-300 hover:text-black disabled:opacity-50 disabled:cursor-not-allowed text-white border border-white/10 px-4 py-2 rounded font-mono text-xs font-bold uppercase tracking-wider flex items-center gap-2 transition-all flex-1 md:flex-none justify-center shadow-lg shadow-black/50"> + <i class="fas fa-play text-[10px]"></i> <span class="md:hidden lg:inline">EXECUTE</span><span class="hidden md:inline lg:hidden">RUN</span> + </button> + </div> + </header> + + <!-- Main Workspace --> + <div id="workspace-container" class="flex-1 flex flex-col md:flex-row min-h-0 z-10 relative"> + + <!-- Code Editor Pane --> + <div id="editor-pane" class="flex-1 flex flex-col h-[60%] md:h-auto min-h-0 border-b md:border-b-0 border-white/10 relative group min-w-[200px]"> + <div class="iframe-shield"></div> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>SRC // main.c</span> + <span class="text-neutral-600">GCC 9.4.0</span> + </div> + + <!-- CodeMirror Container --> + <div id="editor-container" class="relative bg-[#0c0f16] flex-1 overflow-hidden"> + <textarea id="code-input" class="hidden">#include <stdio.h> + +int main() { + printf("Hello C Compiler!\n"); + return 0; +}</textarea> + </div> + + <!-- Mobile Helper Bar --> + <div id="mobile-helper-bar"> + <div class="helper-key" data-char=" ">Tab</div> + <div class="helper-key" data-char=";">;</div> + <div class="helper-key" data-char="=">=</div> + <div class="helper-key" data-char="()">()</div> + <div class="helper-key" data-char="[]">[]</div> + <div class="helper-key" data-char="{}">{}</div> + <div class="helper-key" data-char='""'>""</div> + <div class="helper-key" data-char="''">''</div> + <div class="helper-key" data-char="#">#</div> + <div class="helper-key" data-char="+">+</div> + <div class="helper-key" data-char="-">-</div> + <div class="helper-key" data-char="printf()">printf</div> + </div> + </div> + + <!-- Resizer Handle --> + <div id="resizer"> + <i class="fas fa-grip-lines-vertical text-neutral-600 text-xs"></i> + </div> + + <!-- Terminal Pane --> + <div id="terminal-pane" class="flex-1 flex flex-col h-[40%] md:h-auto min-h-0 bg-[#050505] min-w-[200px]"> + <div class="iframe-shield"></div> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>OUT // TERMINAL</span> + <div class="flex gap-2"> + <button id="copy-btn" class="text-neutral-500 hover:text-white transition-colors" title="Copy Output"><i class="fas fa-copy"></i></button> + <span class="text-neutral-600">XTERM.JS</span> + </div> + </div> + <div class="flex-1 relative"> + <div id="terminal-container" class="absolute inset-0 w-full h-full p-2 overflow-hidden"></div> + </div> + </div> + </div> + + <script type="module"> + import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; + import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; + import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; + + // --- Firebase Config --- + const firebaseConfig = { + apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw", + authDomain: "compiler-aranag-site.firebaseapp.com", + projectId: "compiler-aranag-site", + storageBucket: "compiler-aranag-site.firebasestorage.app", + messagingSenderId: "558890639400", + appId: "1:558890639400:web:125525d10ab51696a5951d", + measurementId: "G-KH9BGSRRGY" + }; + + // Initialize Firebase + const app = initializeApp(firebaseConfig); + const db = getFirestore(app); + const auth = getAuth(app); + + // Attempt initial sign-in + signInAnonymously(auth).catch((error) => { + console.warn("Auto-Auth failed. App will try unauthenticated access.", error.code); + }); + + // --- Helper: Generate ID --- + function generateId(length = 7) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + } + + // --- DOM Elements --- + const runBtn = document.getElementById('run-btn'); + const resetBtn = document.getElementById('reset-btn'); + const shareBtn = document.getElementById('share-btn'); + const copyBtn = document.getElementById('copy-btn'); + const downloadBtn = document.getElementById('download-btn'); + const connDot = document.getElementById('conn-dot'); + const connectionStatus = document.getElementById('connection-status'); + const toast = document.getElementById('toast'); + + // Editor Tool Elements + const undoBtn = document.getElementById('undo-btn'); + const redoBtn = document.getElementById('redo-btn'); + const clearCodeBtn = document.getElementById('clear-code-btn'); + const clearModal = document.getElementById('clear-modal'); + const cancelClearBtn = document.getElementById('cancel-clear-btn'); + const confirmClearBtn = document.getElementById('confirm-clear-btn'); + + // AI Elements + const aiSuggestion = document.getElementById('ai-suggestion'); + const askAiLink = document.getElementById('ask-ai-link'); + const aiModal = document.getElementById('ai-modal'); + const closeModal = document.getElementById('close-modal'); + const cancelFixBtn = document.getElementById('cancel-fix-btn'); + const applyFixBtn = document.getElementById('apply-fix-btn'); + const aiLoading = document.getElementById('ai-loading'); + const aiResult = document.getElementById('ai-result'); + const aiExplanation = document.getElementById('ai-explanation'); + const aiCodePreview = document.getElementById('ai-code-preview'); + const aiErrorMsg = document.getElementById('ai-error-msg'); + + // Layout Elements + const resizer = document.getElementById('resizer'); + const editorPane = document.getElementById('editor-pane'); + const terminalPane = document.getElementById('terminal-pane'); + const workspaceContainer = document.getElementById('workspace-container'); + + // --- State --- + let socket = null; + let currentLine = ""; + let startTime = 0; + let lastSuggestedCode = ""; + let outputBuffer = ""; + + // --- Resizer Logic --- + let isResizing = false; + + resizer.addEventListener('mousedown', (e) => { + isResizing = true; + document.body.classList.add('resizing'); + resizer.classList.add('resizing'); + }); + + document.addEventListener('mousemove', (e) => { + if (!isResizing) return; + + // Only resize on desktop (horizontal layout) + if (window.innerWidth >= 768) { + const containerWidth = workspaceContainer.clientWidth; + const newLeftWidth = (e.clientX / containerWidth) * 100; + + // Constraints (min 20%, max 80%) + if (newLeftWidth > 20 && newLeftWidth < 80) { + editorPane.style.flex = `0 0 ${newLeftWidth}%`; + terminalPane.style.flex = `1`; + // Trigger resize for XTerm and CodeMirror + editor.refresh(); + fitAddon.fit(); + } + } + }); + + document.addEventListener('mouseup', () => { + if (isResizing) { + isResizing = false; + document.body.classList.remove('resizing'); + resizer.classList.remove('resizing'); + editor.refresh(); + fitAddon.fit(); + } + }); + + + // --- CodeMirror Setup --- + const editor = CodeMirror.fromTextArea(document.getElementById("code-input"), { + mode: "text/x-csrc", + theme: "dracula", + lineNumbers: true, + indentUnit: 4, + matchBrackets: true, + autoCloseBrackets: true, + styleActiveLine: true, + inputStyle: "contenteditable", + viewportMargin: Infinity, + scrollbarStyle: "native", // Explicitly use native for custom styling + extraKeys: { + "Backspace": function(cm) { + if (cm.somethingSelected()) { + cm.execCommand("delCharBefore"); + return; + } + var cursor = cm.getCursor(); + var line = cm.getLine(cursor.line); + // If cursor is not at start, and everything before it is whitespace + if (cursor.ch > 0 && /^\s+$/.test(line.slice(0, cursor.ch))) { + cm.execCommand("indentLess"); + } else { + cm.execCommand("delCharBefore"); + } + } + }, + }); + + // Fix resize issues + window.addEventListener('resize', () => { + editor.refresh(); + fitAddon.fit(); + }); + + // Local Auto-Save + const LOCAL_STORAGE_KEY = 'c_compiler_code_autosave'; + editor.on('change', () => { + localStorage.setItem(LOCAL_STORAGE_KEY, editor.getValue()); + }); + + // Load Auto-Save on Start (if not shared) + const savedCode = localStorage.getItem(LOCAL_STORAGE_KEY); + if (savedCode && !window.location.search.includes('share') && !window.location.search.includes('code')) { + editor.setValue(savedCode); + } + + // --- Editor Toolbar Logic --- + undoBtn.addEventListener('click', () => { editor.undo(); editor.focus(); }); + redoBtn.addEventListener('click', () => { editor.redo(); editor.focus(); }); + + clearCodeBtn.addEventListener('click', () => { + clearModal.classList.add('open'); + }); + + cancelClearBtn.addEventListener('click', () => { + clearModal.classList.remove('open'); + }); + + confirmClearBtn.addEventListener('click', () => { + editor.setValue(''); + editor.clearHistory(); + editor.focus(); + clearModal.classList.remove('open'); + showToast("Editor Cleared"); + }); + + clearModal.addEventListener('click', (e) => { + if (e.target === clearModal) clearModal.classList.remove('open'); + }); + + // --- Mobile Helper Bar --- + document.querySelectorAll('.helper-key').forEach(key => { + key.addEventListener('click', (e) => { + const char = key.getAttribute('data-char'); + const doc = editor.getDoc(); + const cursor = doc.getCursor(); + + if (char === '()') { + doc.replaceRange('()', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '[]') { + doc.replaceRange('[]', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '{}') { + doc.replaceRange('{}', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '""') { + doc.replaceRange('""', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "''") { + doc.replaceRange("''", cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "printf()") { + doc.replaceRange('printf("")', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 8}); + } else { + doc.replaceRange(char, cursor); + } + editor.focus(); + }); + }); + + // --- Download Button --- + downloadBtn.addEventListener('click', () => { + const code = editor.getValue(); + const blob = new Blob([code], { type: 'text/x-csrc' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'main.c'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + showToast("Downloaded main.c"); + }); + + window.addEventListener('load', async () => { + const params = new URLSearchParams(window.location.search); + const shareId = params.get('share'); + const sharedCodeOld = params.get('code'); + + if (shareId) { + // Fetch from Firebase + try { + toast.textContent = "Loading shared code..."; + toast.classList.add('show'); + + const docRef = doc(db, "shares", shareId); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + const data = docSnap.data(); + editor.setValue(data.code); + + // Restore Output if it exists + if (data.output && term) { + term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n'); + term.write(data.output.replace(/\n/g, '\r\n')); + term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n'); + } + + toast.textContent = "Code loaded successfully"; + } else { + toast.textContent = "Shared code not found"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } catch (e) { + console.error("Fetch error:", e); + if (e.code === 'permission-denied') { + toast.textContent = "Error: Database Access Denied"; + } else { + toast.textContent = "Error loading code"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } + } else if (sharedCodeOld) { + // Decryption Support: Try LZString first, then fallback to Base64 + let decoded = null; + try { + decoded = LZString.decompressFromEncodedURIComponent(sharedCodeOld); + } catch (e) { console.warn("LZString failed:", e); } + + if (!decoded) { + try { decoded = atob(sharedCodeOld); } catch(e) { console.warn("Base64 failed:", e); } + } + + if (decoded) { + editor.setValue(decoded); + } + } + setTimeout(connect, 500); + }); + + // --- Terminal Setup --- + const term = new Terminal({ + theme: { + background: '#050505', + foreground: '#f5f5f5', + cursor: '#bef264', + selectionBackground: 'rgba(190, 242, 100, 0.3)', + black: '#050505', + green: '#bef264', + yellow: '#facc15', + red: '#ef4444', + }, + fontFamily: "'JetBrains Mono', monospace", + fontSize: 12, + cursorBlink: true, + convertEol: true + }); + const fitAddon = new FitAddon.FitAddon(); + term.loadAddon(fitAddon); + term.open(document.getElementById('terminal-container')); + fitAddon.fit(); + + // Helper: Get Clean Terminal Output + function getTerminalContent() { + if (!term) return ""; + const buffer = term.buffer.active; + let text = ""; + for (let i = 0; i < buffer.length; i++) { + const line = buffer.getLine(i); + if (line) { + let lineText = line.translateToString(true); + // Filter system messages + if(lineText.trim().startsWith("> [") || + lineText.includes("SYSTEM READY") || + lineText.includes("ATTEMPTING") || + lineText.includes("CONNECTION") || + lineText.includes("PREVIOUS OUTPUT") || + lineText.includes("> ----------------") || + lineText.includes("> ./a.out") + ) { + continue; + } + text += lineText + "\n"; + } + } + return text.trim(); + } + + // Custom Key Handler for Ctrl+C Copy + term.attachCustomKeyEventHandler((arg) => { + if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") { + const selection = term.getSelection(); + if (selection) { + fallbackCopyTextToClipboard(selection); + return false; + } + } + return true; + }); + + term.write('\x1b[38;2;115;115;115m> SYSTEM READY.\r\n> ATTEMPTING CONNECTION...\x1b[0m\r\n'); + + // --- WebSocket Logic --- + function connect() { + const url = "wss://compiler-z4x4.onrender.com"; + try { socket = new WebSocket(url); } catch (e) { + term.write(`\r\n\x1b[31m> INVALID URL.\x1b[0m\r\n`); + return; + } + + socket.onopen = () => { + connDot.className = "pulse-dot connected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Connected to Server"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-lime-300"; + + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`); + runBtn.disabled = false; + }; + + socket.onclose = () => { + connDot.className = "pulse-dot disconnected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Disconnected"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-red-500"; + + term.write(`\r\n\x1b[31m> CONNECTION LOST. RECONNECTING...\x1b[0m\r\n`); + runBtn.disabled = true; + setTimeout(connect, 3000); + socket = null; + }; + + socket.onmessage = (event) => { + const msg = JSON.parse(event.data); + if (msg.type === 'stdout') { + let text = msg.data; + outputBuffer += text; + + // Trigger AI Overlay on Error + if (outputBuffer.toLowerCase().includes("error") || outputBuffer.toLowerCase().includes("warning")) { + aiSuggestion.classList.add('visible'); + } + + if (!text.includes('\r')) { + text = text.replace(/\n/g, '\r\n'); + } + term.write(text); + } else if (msg.type === 'status') { + if (msg.msg.includes("Program finished")) { + const duration = (Date.now() - startTime) / 1000; + term.write(`\r\n\x1b[38;2;115;115;115m[Finished in ${duration.toFixed(3)}s]\x1b[0m\r\n`); + } + } else if (msg.type === 'ai_response') { + handleAiResponse(msg.data); + } else if (msg.type === 'ai_error') { + showAiError(msg.msg); + } + }; + } + + // --- Run Logic --- + runBtn.addEventListener('click', () => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + if (document.activeElement) document.activeElement.blur(); + + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + + let code = editor.getValue(); + code = code.replace(/\u00A0/g, " ").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"'); + + // Auto-Flush Injection: Fixes buffered output issues for students + function injectAutoFlush(source) { + const mainRegex = /(int|void)\s+main\s*\([^)]*\)\s*\{/; + const match = source.match(mainRegex); + if (match) { + const insertionPoint = match.index + match[0].length; + return source.slice(0, insertionPoint) + "\n setbuf(stdout, NULL);" + source.slice(insertionPoint); + } + return source; + } + code = injectAutoFlush(code); + + startTime = Date.now(); + term.write('\x1b[32m> gcc main.c -o main -lm -pthread && ./main\x1b[0m\r\n'); + + socket.send(JSON.stringify({ + type: 'run', + code: code, + language: 'c' + })); + + term.focus(); + }); + + // --- AI Feature Logic --- + askAiLink.addEventListener('click', () => { + const errorContext = getTerminalContent(); + const currentCode = editor.getValue(); + + aiModal.classList.add('open'); + aiLoading.classList.remove('hidden'); + aiResult.classList.add('hidden'); + aiErrorMsg.classList.add('hidden'); + applyFixBtn.disabled = true; + + socket.send(JSON.stringify({ + type: 'ai_fix', + code: currentCode, + error: errorContext, + language: 'c' + })); + }); + + function handleAiResponse(data) { + aiLoading.classList.add('hidden'); + aiResult.classList.remove('hidden'); + aiExplanation.textContent = data.explanation; + aiCodePreview.textContent = data.fixed_code; + lastSuggestedCode = data.fixed_code; + applyFixBtn.disabled = false; + } + + function showAiError(msg) { + aiLoading.classList.add('hidden'); + aiErrorMsg.textContent = msg; + aiErrorMsg.classList.remove('hidden'); + } + + applyFixBtn.addEventListener('click', () => { + if (lastSuggestedCode) { + editor.setValue(lastSuggestedCode); + closeAiModal(); + showToast("Fix Applied Successfully!"); + aiSuggestion.classList.remove('visible'); + } + }); + + function closeAiModal() { + aiModal.classList.remove('open'); + } + closeModal.addEventListener('click', closeAiModal); + cancelFixBtn.addEventListener('click', closeAiModal); + aiModal.addEventListener('click', (e) => { + if (e.target === aiModal) closeAiModal(); + }); + + // --- Reset Logic --- + resetBtn.addEventListener('click', () => { + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`); + }); + + // --- Share Functionality with Firebase --- + shareBtn.addEventListener('click', async () => { + const originalIcon = shareBtn.innerHTML; + shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; + shareBtn.disabled = true; + + try { + if (!auth.currentUser) { + try { + await signInAnonymously(auth); + } catch (authError) { + console.warn("Anonymous auth failed:", authError.code); + } + } + + const code = editor.getValue(); + const output = getTerminalContent(); + const shareId = generateId(); + + await setDoc(doc(db, "shares", shareId), { + code: code, + language: 'c', + output: output, + createdAt: new Date().toISOString() + }); + + const url = new URL(window.location.href); + url.searchParams.delete('code'); + url.searchParams.set('share', shareId); + const shareUrl = url.toString(); + + if (navigator.share) { + try { + await navigator.share({ + title: document.title, + text: 'Check out my C code!', + url: shareUrl + }); + } catch (err) { + fallbackCopyTextToClipboard(shareUrl); + } + } else { + fallbackCopyTextToClipboard(shareUrl); + } + } catch (error) { + console.error("Share failed:", error); + if (error.code === 'permission-denied') { + showToast("Share Failed: Access Denied"); + } else { + showToast("Share Failed: " + error.message); + } + } finally { + shareBtn.innerHTML = originalIcon; + shareBtn.disabled = false; + } + }); + + function showToast(msg) { + toast.textContent = msg; + toast.classList.add('show'); + setTimeout(() => toast.classList.remove('show'), 3000); + } + + // --- Smart Copy Function --- + copyBtn.addEventListener('click', () => { + const text = getTerminalContent(); + fallbackCopyTextToClipboard(text); + }); + + function fallbackCopyTextToClipboard(text) { + const textArea = document.createElement("textarea"); + textArea.value = text; + textArea.style.position = "fixed"; + textArea.style.top = "0"; + textArea.style.left = "0"; + textArea.style.opacity = "0"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + showToast("Copied to Clipboard!"); + } catch (err) { + showToast("Copy Failed"); + } + document.body.removeChild(textArea); + } + + // Terminal Input + term.onData((data) => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + + if (data === '\r') { + term.write('\r\n'); + socket.send(JSON.stringify({ type: 'input', data: currentLine + '\n' })); + currentLine = ""; + } else if (data === '\x7f' || data === '\b') { + if (currentLine.length > 0) { + currentLine = currentLine.slice(0, -1); + term.write('\b \b'); + } + } else { + currentLine += data; + term.write(data); + } + }); + </script> +</body> +</html>+ \ No newline at end of file diff --git a/docs/cpp.html b/docs/cpp.html @@ -0,0 +1,1010 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + <title>Amit Dutta // C++ Compiler</title> + <link rel="icon" type="image/x-icon" href="https://compiler.aranag.site/logo.png"> + + <!-- Fonts & Icons --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> + + <!-- Tailwind CSS --> + <script src="https://cdn.tailwindcss.com"></script> + + <!-- CodeMirror 5 (Professional Editor) --> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/clike/clike.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/closebrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/matchbrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/selection/active-line.min.js"></script> + + <!-- Xterm.js --> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" /> + <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script> + <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script> + + <style> + :root { + --bg-main: #050505; + --accent: #bef264; /* Lime 300 */ + --text-muted: #737373; + --border-color: rgba(255, 255, 255, 0.1); + } + + body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-main); + color: #f5f5f5; + height: 100vh; + height: 100dvh; + overflow: hidden; + display: flex; + flex-direction: column; + } + + /* Portfolio Aesthetic */ + .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-heading { font-family: 'Space Grotesk', sans-serif; } + + /* Noise Overlay */ + .bg-noise { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; z-index: 0; opacity: 0.03; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + } + + /* CRT Scanline */ + .crt-scanline { + position: fixed; top: 0; left: 0; width: 100%; height: 2px; + background: rgba(190, 242, 100, 0.1); opacity: 0.5; + pointer-events: none; z-index: 50; + animation: scanline 8s linear infinite; + } + @keyframes scanline { 0% { top: -10vh; } 100% { top: 110vh; } } + + /* CodeMirror Customization */ + .CodeMirror { + height: 100% !important; + font-family: 'JetBrains Mono', monospace; + font-size: 13px; + background-color: #0c0f16 !important; /* Slightly lighter than pure black */ + color: #f8f8f2; + } + .CodeMirror-gutters { + background-color: #0c0f16 !important; + border-right: 1px solid rgba(255,255,255,0.05) !important; + } + .CodeMirror-linenumber { + color: #555 !important; + } + .CodeMirror-cursor { + border-left: 2px solid var(--accent) !important; + } + .CodeMirror-selected { + background: rgba(190, 242, 100, 0.2) !important; + } + .cm-s-dracula .CodeMirror-activeline-background { + background: rgba(255, 255, 255, 0.03) !important; + } + + /* Scrollbar styling */ + .CodeMirror-scroll::-webkit-scrollbar, + .xterm-viewport::-webkit-scrollbar, + .custom-scrollbar::-webkit-scrollbar { + width: 6px; height: 6px; + } + .CodeMirror-scroll::-webkit-scrollbar-track, + .xterm-viewport::-webkit-scrollbar-track, + .custom-scrollbar::-webkit-scrollbar-track { + background: #050505; + } + .CodeMirror-scroll::-webkit-scrollbar-thumb, + .xterm-viewport::-webkit-scrollbar-thumb, + .custom-scrollbar::-webkit-scrollbar-thumb { + background: #333; border-radius: 3px; + } + + /* Mobile Helper Bar */ + #mobile-helper-bar { + display: none; /* Shown via JS on mobile */ + background: #151515; + border-top: 1px solid rgba(255,255,255,0.1); + padding: 8px; + overflow-x: auto; + white-space: nowrap; + -webkit-overflow-scrolling: touch; + } + @media (max-width: 768px) { + #mobile-helper-bar { display: flex; gap: 8px; } + } + .helper-key { + background: rgba(255,255,255,0.1); + color: var(--accent); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 4px; + padding: 6px 12px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + font-weight: bold; + cursor: pointer; + user-select: none; + } + .helper-key:active { background: var(--accent); color: black; } + + /* Toast Notification */ + .toast { + position: fixed; + bottom: 2rem; + left: 50%; + transform: translateX(-50%) translateY(100px); + background: #1a1a1a; + border: 1px solid var(--accent); + color: var(--accent); + padding: 0.5rem 1.5rem; + border-radius: 9999px; + font-family: 'JetBrains Mono', monospace; + font-size: 0.8rem; + transition: transform 0.3s ease; + z-index: 100; + } + .toast.show { transform: translateX(-50%) translateY(0); } + + /* Connection Dot Pulse */ + .pulse-dot { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); + animation: pulse-white 2s infinite; + } + .pulse-dot.connected { + background-color: #bef264; /* Lime */ + box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); + animation: pulse-lime 2s infinite; + } + .pulse-dot.disconnected { + background-color: #ef4444; /* Red */ + box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); + animation: pulse-red 2s infinite; + } + + @keyframes pulse-lime { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(190, 242, 100, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0); } + } + @keyframes pulse-red { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } + } + + /* AI Text Overlay */ + .ai-overlay { + position: absolute; + bottom: 10px; + right: 20px; + background: rgba(20, 20, 20, 0.9); + border: 1px solid #ef4444; + color: #fca5a5; + padding: 8px 12px; + border-radius: 6px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + z-index: 60; + display: none; + backdrop-filter: blur(4px); + animation: slideIn 0.3s ease-out; + box-shadow: 0 4px 12px rgba(0,0,0,0.5); + } + .ai-overlay.visible { display: flex; align-items: center; gap: 8px; } + + .ai-link { + color: #fff; + text-decoration: underline; + text-decoration-style: dotted; + text-underline-offset: 4px; + cursor: pointer; + font-weight: bold; + transition: color 0.2s; + } + .ai-link:hover { color: #bef264; text-decoration-style: solid; } + + @keyframes slideIn { + from { transform: translateY(20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } + } + + /* Modals (AI & Clear) */ + .modal-overlay { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.8); backdrop-filter: blur(5px); + z-index: 200; display: none; align-items: center; justify-content: center; + } + .modal-overlay.open { display: flex; } + + .modal-content { + background: #0f0f0f; + border: 1px solid var(--accent); + width: 90%; max-width: 600px; + border-radius: 12px; + display: flex; flex-direction: column; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + overflow: hidden; + animation: modalPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + } + + @keyframes modalPop { + 0% { transform: scale(0.9); opacity: 0; } + 100% { transform: scale(1); opacity: 1; } + } + + /* Editor Toolbar Buttons */ + .editor-btn { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + color: #737373; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s; + cursor: pointer; + } + .editor-btn:hover { + background: rgba(255,255,255,0.1); + color: #fff; + border-color: rgba(255,255,255,0.3); + } + .editor-btn.danger:hover { + background: rgba(239, 68, 68, 0.1); + color: #ef4444; + border-color: #ef4444; + } + </style> +</head> +<body class="antialiased selection:bg-lime-300 selection:text-black"> + + <div class="bg-noise"></div> + <div class="crt-scanline"></div> + <div id="toast" class="toast">Link Copied to Clipboard!</div> + + <!-- AI Overlay in Terminal --> + <div id="ai-suggestion" class="ai-overlay"> + <i class="fas fa-exclamation-triangle text-red-500"></i> + <span>Error detected. <span id="ask-ai-link" class="ai-link">Ask AI</span> to fix it.</span> + </div> + + <!-- Clear Confirmation Modal --> + <div id="clear-modal" class="modal-overlay"> + <div class="modal-content max-w-[320px] p-0 border-red-500/50"> + <div class="bg-red-500/10 px-6 py-4 border-b border-red-500/20"> + <h3 class="font-heading font-bold text-lg text-red-500 flex items-center gap-2"> + <i class="fas fa-exclamation-circle"></i> CLEAR CODE + </h3> + </div> + <div class="p-6 text-center"> + <p class="text-neutral-300 text-sm font-sans mb-6">Are you sure you want to clear the editor? This action will remove all current code.</p> + <div class="flex justify-center gap-3"> + <button id="cancel-clear-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all border border-transparent">Cancel</button> + <button id="confirm-clear-btn" class="bg-red-500/10 hover:bg-red-500 hover:text-black text-red-500 border border-red-500/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2"> + <i class="fas fa-trash-alt"></i> Confirm + </button> + </div> + </div> + </div> + </div> + + <!-- AI Fix Modal --> + <div id="ai-modal" class="modal-overlay"> + <div class="modal-content max-h-[80vh]"> + <!-- Modal Header --> + <div class="bg-white/5 px-6 py-4 border-b border-white/10 flex justify-between items-center"> + <h3 class="font-heading font-bold text-lg text-lime-300 flex items-center gap-2"> + <i class="fas fa-robot"></i> AI Diagnosis + </h3> + <button id="close-modal" class="text-neutral-500 hover:text-white transition-colors"> + <i class="fas fa-times"></i> + </button> + </div> + + <!-- Modal Body --> + <div class="p-6 overflow-y-auto custom-scrollbar flex-1"> + <div id="ai-loading" class="hidden flex flex-col items-center justify-center py-8 gap-4"> + <div class="pulse-dot connected" style="width: 12px; height: 12px;"></div> + <p class="font-mono text-neutral-400 text-sm animate-pulse">Analyzing compile error...</p> + </div> + + <div id="ai-result" class="hidden space-y-4"> + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Explanation</h4> + <p id="ai-explanation" class="text-sm text-neutral-200 leading-relaxed font-sans"></p> + </div> + + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Suggested Fix</h4> + <div class="relative group"> + <pre id="ai-code-preview" class="bg-black/30 border border-white/10 p-3 rounded text-xs font-mono text-lime-100 overflow-x-auto custom-scrollbar"></pre> + </div> + </div> + </div> + + <div id="ai-error-msg" class="hidden text-red-400 text-sm font-mono text-center py-4"></div> + </div> + + <!-- Modal Footer --> + <div class="bg-white/5 px-6 py-4 border-t border-white/10 flex justify-end gap-3"> + <button id="cancel-fix-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all">Dismiss</button> + <button id="apply-fix-btn" disabled class="bg-lime-300/10 hover:bg-lime-300 hover:text-black text-lime-300 border border-lime-300/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"> + <i class="fas fa-check"></i> Apply Fix + </button> + </div> + </div> + </div> + + <!-- Header (Responsive) --> + <header class="h-auto md:h-16 flex flex-col md:flex-row items-center justify-between px-4 py-3 md:px-6 shrink-0 border-b border-white/10 z-20 bg-neutral-900/50 backdrop-blur-md gap-3 md:gap-4"> + + <!-- Top Row: Title & Editor Tools --> + <div class="flex items-center justify-between w-full md:w-auto gap-6"> + <h1 class="text-lg md:text-xl font-heading font-bold text-white tracking-tight flex items-center"> + <span class="text-lime-300 mr-2">//</span>CPP.COMPILER + <span id="conn-dot" class="pulse-dot disconnected ml-3" title="Disconnected"></span> + </h1> + + <!-- Editor Tools --> + <div class="flex items-center gap-2"> + <button id="undo-btn" class="editor-btn" title="Undo (Ctrl+Z)"> + <i class="fas fa-undo text-xs"></i> + </button> + <button id="redo-btn" class="editor-btn" title="Redo (Ctrl+Y)"> + <i class="fas fa-redo text-xs"></i> + </button> + <div class="w-px h-4 bg-white/10 mx-1"></div> + <button id="clear-code-btn" class="editor-btn danger" title="Clear Code"> + <i class="fas fa-times text-xs"></i> + </button> + </div> + + <!-- Mobile Only: Exit Link --> + <a href="./index.html" class="md:hidden font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors ml-auto">[ EXIT ]</a> + </div> + + <!-- Middle: Connection Text --> + <div class="hidden md:flex items-center gap-2 font-mono text-xs text-neutral-500"> + <span id="connection-status">Connecting to server...</span> + </div> + + <!-- Bottom/Right: Buttons --> + <div class="flex items-center gap-2 w-full md:w-auto justify-end"> + <a href="./index.html" class="hidden md:inline font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors mr-2">[ EXIT ]</a> + + <button id="download-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Download .cpp"> + <i class="fas fa-download"></i> + </button> + + <button id="reset-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Reset Terminal"> + <i class="fas fa-rotate-left"></i> + </button> + + <button id="share-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Share Code"> + <i class="fas fa-share-alt"></i> + </button> + + <button id="run-btn" disabled class="bg-white/5 hover:bg-lime-300 hover:text-black disabled:opacity-50 disabled:cursor-not-allowed text-white border border-white/10 px-4 py-2 rounded font-mono text-xs font-bold uppercase tracking-wider flex items-center gap-2 transition-all flex-1 md:flex-none justify-center shadow-lg shadow-black/50"> + <i class="fas fa-play text-[10px]"></i> <span class="md:hidden lg:inline">EXECUTE</span><span class="hidden md:inline lg:hidden">RUN</span> + </button> + </div> + </header> + + <!-- Main Workspace --> + <div class="flex-1 flex flex-col md:flex-row min-h-0 z-10 relative"> + + <!-- Code Editor --> + <div class="flex-1 flex flex-col h-[60%] md:h-auto min-h-0 border-b md:border-b-0 md:border-r border-white/10 relative group"> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>SRC // main.cpp</span> + <span class="text-neutral-600">G++ 9.4.0</span> + </div> + + <!-- CodeMirror Container --> + <div id="editor-container" class="relative bg-[#0c0f16] flex-1 overflow-hidden"> + <textarea id="code-input" class="hidden">#include <iostream> + +int main() { + std::cout << "Hello C++ Compiler!" << std::endl; + return 0; +}</textarea> + </div> + + <!-- Mobile Helper Bar --> + <div id="mobile-helper-bar"> + <div class="helper-key" data-char=" ">Tab</div> + <div class="helper-key" data-char=";">;</div> + <div class="helper-key" data-char="=">=</div> + <div class="helper-key" data-char="()">()</div> + <div class="helper-key" data-char="[]">[]</div> + <div class="helper-key" data-char="{}">{}</div> + <div class="helper-key" data-char='""'>""</div> + <div class="helper-key" data-char="''">''</div> + <div class="helper-key" data-char="#">#</div> + <div class="helper-key" data-char="<<">&lt;&lt;</div> + <div class="helper-key" data-char=">>">&gt;&gt;</div> + <div class="helper-key" data-char="cout">cout</div> + </div> + </div> + + <!-- Terminal --> + <div class="flex-1 flex flex-col h-[40%] md:h-auto min-h-0 bg-[#050505]"> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>OUT // TERMINAL</span> + <div class="flex gap-2"> + <button id="copy-btn" class="text-neutral-500 hover:text-white transition-colors" title="Copy Output"><i class="fas fa-copy"></i></button> + <span class="text-neutral-600">XTERM.JS</span> + </div> + </div> + <div class="flex-1 relative"> + <div id="terminal-container" class="absolute inset-0 w-full h-full p-2 overflow-hidden"></div> + </div> + </div> + </div> + + <script type="module"> + import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; + import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; + import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; + + // --- Firebase Config --- + const firebaseConfig = { + apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw", + authDomain: "compiler-aranag-site.firebaseapp.com", + projectId: "compiler-aranag-site", + storageBucket: "compiler-aranag-site.firebasestorage.app", + messagingSenderId: "558890639400", + appId: "1:558890639400:web:125525d10ab51696a5951d", + measurementId: "G-KH9BGSRRGY" + }; + + // Initialize Firebase + const app = initializeApp(firebaseConfig); + const db = getFirestore(app); + const auth = getAuth(app); + + // Attempt initial sign-in + signInAnonymously(auth).catch((error) => { + console.warn("Auto-Auth failed. App will try unauthenticated access.", error.code); + }); + + // --- Helper: Generate ID --- + function generateId(length = 7) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + } + + // --- DOM Elements --- + const runBtn = document.getElementById('run-btn'); + const resetBtn = document.getElementById('reset-btn'); + const shareBtn = document.getElementById('share-btn'); + const copyBtn = document.getElementById('copy-btn'); + const downloadBtn = document.getElementById('download-btn'); + const connDot = document.getElementById('conn-dot'); + const connectionStatus = document.getElementById('connection-status'); + const toast = document.getElementById('toast'); + + // Editor Tool Elements + const undoBtn = document.getElementById('undo-btn'); + const redoBtn = document.getElementById('redo-btn'); + const clearCodeBtn = document.getElementById('clear-code-btn'); + const clearModal = document.getElementById('clear-modal'); + const cancelClearBtn = document.getElementById('cancel-clear-btn'); + const confirmClearBtn = document.getElementById('confirm-clear-btn'); + + // AI Elements + const aiSuggestion = document.getElementById('ai-suggestion'); + const askAiLink = document.getElementById('ask-ai-link'); + const aiModal = document.getElementById('ai-modal'); + const closeModal = document.getElementById('close-modal'); + const cancelFixBtn = document.getElementById('cancel-fix-btn'); + const applyFixBtn = document.getElementById('apply-fix-btn'); + const aiLoading = document.getElementById('ai-loading'); + const aiResult = document.getElementById('ai-result'); + const aiExplanation = document.getElementById('ai-explanation'); + const aiCodePreview = document.getElementById('ai-code-preview'); + const aiErrorMsg = document.getElementById('ai-error-msg'); + + // --- State --- + let socket = null; + let currentLine = ""; + let startTime = 0; + let lastSuggestedCode = ""; + let outputBuffer = ""; + + // --- CodeMirror Setup --- + const editor = CodeMirror.fromTextArea(document.getElementById("code-input"), { + mode: "text/x-c++src", + theme: "dracula", + lineNumbers: true, + indentUnit: 4, + matchBrackets: true, + autoCloseBrackets: true, + styleActiveLine: true, + inputStyle: "contenteditable", + viewportMargin: Infinity, + extraKeys: { + "Backspace": function(cm) { + if (cm.somethingSelected()) { + cm.execCommand("delCharBefore"); + return; + } + var cursor = cm.getCursor(); + var line = cm.getLine(cursor.line); + // If cursor is not at start, and everything before it is whitespace + if (cursor.ch > 0 && /^\s+$/.test(line.slice(0, cursor.ch))) { + cm.execCommand("indentLess"); + } else { + cm.execCommand("delCharBefore"); + } + } + }, + }); + + // Fix resize issues + window.addEventListener('resize', () => editor.refresh()); + + // Local Auto-Save + const LOCAL_STORAGE_KEY = 'cpp_compiler_code_autosave'; + editor.on('change', () => { + localStorage.setItem(LOCAL_STORAGE_KEY, editor.getValue()); + }); + + // Load Auto-Save on Start (if not shared) + const savedCode = localStorage.getItem(LOCAL_STORAGE_KEY); + if (savedCode && !window.location.search.includes('share') && !window.location.search.includes('code')) { + editor.setValue(savedCode); + } + + // --- Editor Toolbar Logic --- + undoBtn.addEventListener('click', () => { editor.undo(); editor.focus(); }); + redoBtn.addEventListener('click', () => { editor.redo(); editor.focus(); }); + + clearCodeBtn.addEventListener('click', () => { + clearModal.classList.add('open'); + }); + + cancelClearBtn.addEventListener('click', () => { + clearModal.classList.remove('open'); + }); + + confirmClearBtn.addEventListener('click', () => { + editor.setValue(''); + editor.clearHistory(); + editor.focus(); + clearModal.classList.remove('open'); + showToast("Editor Cleared"); + }); + + clearModal.addEventListener('click', (e) => { + if (e.target === clearModal) clearModal.classList.remove('open'); + }); + + // --- Mobile Helper Bar --- + document.querySelectorAll('.helper-key').forEach(key => { + key.addEventListener('click', (e) => { + const char = key.getAttribute('data-char'); + const doc = editor.getDoc(); + const cursor = doc.getCursor(); + + if (char === '()') { + doc.replaceRange('()', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '[]') { + doc.replaceRange('[]', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '{}') { + doc.replaceRange('{}', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '""') { + doc.replaceRange('""', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "''") { + doc.replaceRange("''", cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "cout") { + doc.replaceRange('cout << ', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 8}); + } else { + doc.replaceRange(char, cursor); + } + editor.focus(); + }); + }); + + // --- Download Button --- + downloadBtn.addEventListener('click', () => { + const code = editor.getValue(); + const blob = new Blob([code], { type: 'text/x-c++src' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'main.cpp'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + showToast("Downloaded main.cpp"); + }); + + window.addEventListener('load', async () => { + const params = new URLSearchParams(window.location.search); + const shareId = params.get('share'); + const sharedCodeOld = params.get('code'); + + if (shareId) { + // Fetch from Firebase + try { + toast.textContent = "Loading shared code..."; + toast.classList.add('show'); + + const docRef = doc(db, "shares", shareId); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + const data = docSnap.data(); + editor.setValue(data.code); + + // Restore Output if it exists + if (data.output && term) { + term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n'); + term.write(data.output.replace(/\n/g, '\r\n')); + term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n'); + } + + toast.textContent = "Code loaded successfully"; + } else { + toast.textContent = "Shared code not found"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } catch (e) { + console.error("Fetch error:", e); + if (e.code === 'permission-denied') { + toast.textContent = "Error: Database Access Denied"; + } else { + toast.textContent = "Error loading code"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } + } else if (sharedCodeOld) { + // Fallback for Base64 + try { editor.setValue(atob(sharedCodeOld)); } + catch(e) {} + } + setTimeout(connect, 500); + }); + + // --- Terminal Setup --- + const term = new Terminal({ + theme: { + background: '#050505', + foreground: '#f5f5f5', + cursor: '#bef264', + selectionBackground: 'rgba(190, 242, 100, 0.3)', + black: '#050505', + green: '#bef264', + yellow: '#facc15', + red: '#ef4444', + }, + fontFamily: "'JetBrains Mono', monospace", + fontSize: 12, + cursorBlink: true, + convertEol: true + }); + const fitAddon = new FitAddon.FitAddon(); + term.loadAddon(fitAddon); + term.open(document.getElementById('terminal-container')); + fitAddon.fit(); + window.addEventListener('resize', () => fitAddon.fit()); + + // Helper: Get Clean Terminal Output + function getTerminalContent() { + if (!term) return ""; + const buffer = term.buffer.active; + let text = ""; + for (let i = 0; i < buffer.length; i++) { + const line = buffer.getLine(i); + if (line) { + let lineText = line.translateToString(true); + // Filter system messages + if(lineText.trim().startsWith("> [") || + lineText.includes("SYSTEM READY") || + lineText.includes("ATTEMPTING") || + lineText.includes("CONNECTION") || + lineText.includes("PREVIOUS OUTPUT") || + lineText.includes("> ----------------") || + lineText.includes("> ./a.out") + ) { + continue; + } + text += lineText + "\n"; + } + } + return text.trim(); + } + + // Custom Key Handler for Ctrl+C Copy + term.attachCustomKeyEventHandler((arg) => { + if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") { + const selection = term.getSelection(); + if (selection) { + fallbackCopyTextToClipboard(selection); + return false; + } + } + return true; + }); + + term.write('\x1b[38;2;115;115;115m> SYSTEM READY.\r\n> ATTEMPTING CONNECTION...\x1b[0m\r\n'); + + // --- WebSocket Logic --- + function connect() { + const url = "wss://compiler-z4x4.onrender.com"; + try { socket = new WebSocket(url); } catch (e) { + term.write(`\r\n\x1b[31m> INVALID URL.\x1b[0m\r\n`); + return; + } + + socket.onopen = () => { + connDot.className = "pulse-dot connected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Connected to Server"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-lime-300"; + + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`); + runBtn.disabled = false; + }; + + socket.onclose = () => { + connDot.className = "pulse-dot disconnected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Disconnected"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-red-500"; + + term.write(`\r\n\x1b[31m> CONNECTION LOST. RECONNECTING...\x1b[0m\r\n`); + runBtn.disabled = true; + setTimeout(connect, 3000); + socket = null; + }; + + socket.onmessage = (event) => { + const msg = JSON.parse(event.data); + if (msg.type === 'stdout') { + let text = msg.data; + outputBuffer += text; + + // Trigger AI Overlay on Error + if (outputBuffer.toLowerCase().includes("error") || outputBuffer.toLowerCase().includes("warning")) { + aiSuggestion.classList.add('visible'); + } + + if (!text.includes('\r')) { + text = text.replace(/\n/g, '\r\n'); + } + term.write(text); + } else if (msg.type === 'status') { + if (msg.msg.includes("Program finished")) { + const duration = (Date.now() - startTime) / 1000; + term.write(`\r\n\x1b[38;2;115;115;115m[Finished in ${duration.toFixed(3)}s]\x1b[0m\r\n`); + } + } else if (msg.type === 'ai_response') { + handleAiResponse(msg.data); + } else if (msg.type === 'ai_error') { + showAiError(msg.msg); + } + }; + } + + // --- Run Logic --- + runBtn.addEventListener('click', () => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + if (document.activeElement) document.activeElement.blur(); + + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + + let code = editor.getValue(); + code = code.replace(/\u00A0/g, " ").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"'); + + startTime = Date.now(); + term.write('\x1b[32m> g++ main.cpp -o main && ./main\x1b[0m\r\n'); + + socket.send(JSON.stringify({ + type: 'run', + code: code, + language: 'cpp' + })); + + term.focus(); + }); + + // --- AI Feature Logic --- + askAiLink.addEventListener('click', () => { + const errorContext = getTerminalContent(); + const currentCode = editor.getValue(); + + aiModal.classList.add('open'); + aiLoading.classList.remove('hidden'); + aiResult.classList.add('hidden'); + aiErrorMsg.classList.add('hidden'); + applyFixBtn.disabled = true; + + socket.send(JSON.stringify({ + type: 'ai_fix', + code: currentCode, + error: errorContext, + language: 'cpp' + })); + }); + + function handleAiResponse(data) { + aiLoading.classList.add('hidden'); + aiResult.classList.remove('hidden'); + aiExplanation.textContent = data.explanation; + aiCodePreview.textContent = data.fixed_code; + lastSuggestedCode = data.fixed_code; + applyFixBtn.disabled = false; + } + + function showAiError(msg) { + aiLoading.classList.add('hidden'); + aiErrorMsg.textContent = msg; + aiErrorMsg.classList.remove('hidden'); + } + + applyFixBtn.addEventListener('click', () => { + if (lastSuggestedCode) { + editor.setValue(lastSuggestedCode); + closeAiModal(); + showToast("Fix Applied Successfully!"); + aiSuggestion.classList.remove('visible'); + } + }); + + function closeAiModal() { + aiModal.classList.remove('open'); + } + closeModal.addEventListener('click', closeAiModal); + cancelFixBtn.addEventListener('click', closeAiModal); + aiModal.addEventListener('click', (e) => { + if (e.target === aiModal) closeAiModal(); + }); + + // --- Reset Logic --- + resetBtn.addEventListener('click', () => { + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`); + }); + + // --- Share Functionality with Firebase --- + shareBtn.addEventListener('click', async () => { + const originalIcon = shareBtn.innerHTML; + shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; + shareBtn.disabled = true; + + try { + if (!auth.currentUser) { + try { + await signInAnonymously(auth); + } catch (authError) { + console.warn("Anonymous auth failed:", authError.code); + } + } + + const code = editor.getValue(); + const output = getTerminalContent(); + const shareId = generateId(); + + await setDoc(doc(db, "shares", shareId), { + code: code, + language: 'cpp', + output: output, + createdAt: new Date().toISOString() + }); + + const url = new URL(window.location.href); + url.searchParams.delete('code'); + url.searchParams.set('share', shareId); + const shareUrl = url.toString(); + + if (navigator.share) { + try { + await navigator.share({ + title: document.title, + text: 'Check out my C++ code!', + url: shareUrl + }); + } catch (err) { + fallbackCopyTextToClipboard(shareUrl); + } + } else { + fallbackCopyTextToClipboard(shareUrl); + } + } catch (error) { + console.error("Share failed:", error); + if (error.code === 'permission-denied') { + showToast("Share Failed: Access Denied"); + } else { + showToast("Share Failed: " + error.message); + } + } finally { + shareBtn.innerHTML = originalIcon; + shareBtn.disabled = false; + } + }); + + function showToast(msg) { + toast.textContent = msg; + toast.classList.add('show'); + setTimeout(() => toast.classList.remove('show'), 3000); + } + + // --- Smart Copy Function --- + copyBtn.addEventListener('click', () => { + const text = getTerminalContent(); + fallbackCopyTextToClipboard(text); + }); + + function fallbackCopyTextToClipboard(text) { + const textArea = document.createElement("textarea"); + textArea.value = text; + textArea.style.position = "fixed"; + textArea.style.top = "0"; + textArea.style.left = "0"; + textArea.style.opacity = "0"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + showToast("Copied to Clipboard!"); + } catch (err) { + showToast("Copy Failed"); + } + document.body.removeChild(textArea); + } + + // Terminal Input + term.onData((data) => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + + if (data === '\r') { + term.write('\r\n'); + socket.send(JSON.stringify({ type: 'input', data: currentLine + '\n' })); + currentLine = ""; + } else if (data === '\x7f' || data === '\b') { + if (currentLine.length > 0) { + currentLine = currentLine.slice(0, -1); + term.write('\b \b'); + } + } else { + currentLine += data; + term.write(data); + } + }); + </script> +</body> +</html>+ \ No newline at end of file diff --git a/docs/docs.html b/docs/docs.html @@ -1,247 +1,519 @@ <!DOCTYPE html> -<html lang="en" class="dark"> +<html lang="en" class="scroll-smooth"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Ada AI - Documentation</title> -<link rel="icon" type="image/png" href="logo.png"> + <title>Documentation // Cloud Code Compiler</title> + <link rel="icon" type="image/x-icon" href="https://compiler.aranag.site/logo.png"> + + <!-- Fonts --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet"> + + <!-- Libraries --> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> <script src="https://cdn.tailwindcss.com"></script> - <script> - tailwind.config = { - darkMode: 'class', - theme: { - extend: { - colors: { - gemini: { - bg: '#131314', - surface: '#1E1F20', - text: '#E3E3E3', - blue: '#A8C7FA' - } - }, - fontFamily: { - sans: ['Inter', 'sans-serif'], - mono: ['JetBrains Mono', 'monospace'], - } - } - } + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"> + + <style> + :root { + --bg-main: #050505; + --accent: #bef264; /* Lime 300 */ + --text-muted: #737373; + --border-color: rgba(255, 255, 255, 0.1); } - </script> - <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> + + body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-main); + color: #f5f5f5; + line-height: 1.6; + } + + .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-heading { font-family: 'Space Grotesk', sans-serif; } + + /* Custom Scrollbar */ + ::-webkit-scrollbar { width: 8px; } + ::-webkit-scrollbar-track { background: #050505; } + ::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; } + ::-webkit-scrollbar-thumb:hover { background: #555; } + + /* Doc Sections */ + .doc-section { + margin-bottom: 4rem; + scroll-margin-top: 6rem; + border-bottom: 1px solid rgba(255,255,255,0.05); + padding-bottom: 3rem; + } + .doc-section:last-child { border-bottom: none; } + + .code-block { + background: #0f1115; + border: 1px solid var(--border-color); + border-radius: 0.75rem; + padding: 1rem; + margin: 1.5rem 0; + font-size: 0.9rem; + overflow-x: auto; + } + + .nav-link { + display: block; + padding: 0.5rem 1rem; + color: var(--text-muted); + border-left: 2px solid transparent; + transition: all 0.2s; + } + .nav-link:hover, .nav-link.active { + color: var(--accent); + border-left-color: var(--accent); + background: rgba(190, 242, 100, 0.05); + } + + /* Noise Overlay */ + .bg-noise { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; z-index: 0; opacity: 0.03; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + } + </style> </head> -<body class="bg-gemini-bg text-gemini-text font-sans p-6 md:p-12 leading-relaxed selection:bg-gemini-blue selection:text-black"> - <div class="max-w-4xl mx-auto"> - <!-- Header --> - <header class="mb-12 border-b border-gray-800 pb-8"> - <a href="/" class="inline-flex items-center text-gemini-blue hover:text-white transition-colors mb-6 font-medium text-sm"> - <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg> - Back to App - </a> - <h1 class="text-4xl md:text-5xl font-bold text-white mb-4 tracking-tight">Ada AI Documentation</h1> - <p class="text-xl text-gray-400 font-light">Comprehensive guide to the architecture, usage, and contribution workflow for the Ada AI Coding Assistant.</p> - </header> +<body class="antialiased selection:bg-lime-300 selection:text-black"> + + <div class="bg-noise"></div> + + <!-- Layout Grid --> + <div class="max-w-7xl mx-auto px-6 py-12 grid grid-cols-1 lg:grid-cols-4 gap-12 relative z-10"> - <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> - <!-- Sidebar Nav --> - <nav class="hidden md:block col-span-1 space-y-1 sticky top-8 h-fit"> - <a href="#introduction" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">1. Introduction</a> - <a href="#how-it-works" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">2. System Architecture</a> - <a href="#data-privacy" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">3. Data & Privacy</a> - <a href="#features" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">4. Features Guide</a> - <a href="#contributing" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">5. Contributing</a> - <a href="#support" class="block py-2 px-3 rounded-lg hover:bg-gemini-surface text-gray-400 hover:text-white transition-colors text-sm">6. Support</a> + <!-- Sidebar Navigation --> + <aside class="hidden lg:block col-span-1 sticky top-12 h-[calc(100vh-6rem)] overflow-y-auto pr-4"> + <div class="mb-8"> + <a href="./index.html" class="flex items-center gap-2 group"> + <i class="fas fa-arrow-left text-neutral-500 group-hover:text-white transition-colors"></i> + <span class="font-heading font-bold text-xl text-white">Back to Home</span> + </a> + </div> + + <nav class="space-y-1"> + <p class="px-4 text-xs font-mono text-neutral-500 uppercase tracking-widest mb-2">Core System</p> + <a href="#architecture" class="nav-link font-mono text-sm">01. Architecture</a> + <a href="#editor" class="nav-link font-mono text-sm text-lime-300">02. Editor & Tools (NEW)</a> + <a href="#communication" class="nav-link font-mono text-sm">03. WebSocket I/O</a> + + <p class="px-4 text-xs font-mono text-neutral-500 uppercase tracking-widest mb-2 mt-6">Engines</p> + <a href="#engines" class="nav-link font-mono text-sm">04. Execution Engines</a> + + <p class="px-4 text-xs font-mono text-neutral-500 uppercase tracking-widest mb-2 mt-6">Intelligence</p> + <a href="#ai-debug" class="nav-link font-mono text-sm">05. AI Auto-Debug</a> + + <p class="px-4 text-xs font-mono text-neutral-500 uppercase tracking-widest mb-2 mt-6">Data</p> + <a href="#persistence" class="nav-link font-mono text-sm">06. Sharing & Persistence</a> + <a href="#lifecycle" class="nav-link font-mono text-sm">07. Data Lifecycle</a> + <a href="#security" class="nav-link font-mono text-sm">08. Security</a> + + <p class="px-4 text-xs font-mono text-neutral-500 uppercase tracking-widest mb-2 mt-6">Community</p> + <a href="#contribution" class="nav-link font-mono text-sm">09. Contribution</a> + <a href="#disclaimer" class="nav-link font-mono text-sm text-red-400">10. Disclaimer</a> </nav> - <!-- Content --> - <div class="col-span-1 md:col-span-3 space-y-16"> - - <!-- Section 1: Introduction --> - <section id="introduction"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">1</span> - Introduction - </h2> - <p class="text-gray-300 mb-4"> - Ada AI is a specialized coding assistant built to provide students and developers with accurate, context-aware debugging and refactoring help. Unlike generic AI chatbots, Ada is engineered specifically for software development workflows, integrating a real-time code editor directly into the conversation loop. - </p> - <div class="bg-gemini-surface border-l-4 border-gemini-blue p-4 rounded-r-lg"> - <p class="text-sm text-gray-300"><strong>Core Philosophy:</strong> Simplicity, Speed, and Strict Data Segregation. Ada connects you to Google's Gemini 2.5 Flash model while keeping your data isolated within your own Firebase document scope.</p> + <div class="mt-12 p-4 rounded-xl bg-white/5 border border-white/10"> + <p class="text-xs text-neutral-400 mb-2">Tech Stack</p> + <div class="flex flex-wrap gap-2"> + <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">CodeMirror</span> + <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">Gemini 2.5</span> + <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">Firebase</span> + <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">aiohttp</span> + </div> + </div> + </aside> + + <!-- Main Content --> + <main class="col-span-1 lg:col-span-3"> + + <!-- Mobile Header --> + <div class="lg:hidden mb-12"> + <a href="./index.html" class="flex items-center gap-2 text-neutral-400 hover:text-white mb-6"> + <i class="fas fa-arrow-left"></i> Return Home + </a> + <h1 class="text-4xl font-heading font-bold text-white">System Documentation</h1> + </div> + + <!-- Intro --> + <div class="mb-16 border-b border-white/10 pb-12"> + <h1 class="hidden lg:block text-5xl font-heading font-bold text-white mb-6">System Documentation</h1> + <p class="text-xl text-neutral-400 leading-relaxed max-w-3xl"> + A comprehensive technical overview of the Cloud Code Compiler v2.0. This document covers the full stack, from the CodeMirror-enhanced frontend to the AI-powered debugging backend and real-time execution engines. + </p> + </div> + + <!-- 01 Architecture --> + <section id="architecture" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">01.</span> Architecture + </h2> + <p class="text-neutral-300 mb-4"> + The platform operates as a distributed system designed for low-latency feedback. It replaces traditional HTTP polling with persistent WebSocket connections, enabling interactive coding (REPL-like behavior) over the web. + </p> + <div class="grid grid-cols-1 md:grid-cols-2 gap-6 my-8"> + <div class="p-6 rounded-xl bg-white/5 border border-white/10"> + <h3 class="text-white font-bold mb-2"><i class="fas fa-laptop-code text-lime-300 mr-2"></i> Frontend (Client)</h3> + <ul class="text-sm text-neutral-400 space-y-2"> + <li>• <strong>Editor:</strong> CodeMirror 5 (Dracula Theme)</li> + <li>• <strong>Terminal:</strong> Xterm.js with FitAddon</li> + <li>• <strong>State:</strong> Browser LocalStorage</li> + <li>• <strong>Intelligence:</strong> Client-side Error Parsing</li> + </ul> </div> - </section> - - <!-- Section 2: How It Works --> - <section id="how-it-works"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">2</span> - System Architecture - </h2> - - <div class="space-y-8"> - <div> - <h3 class="text-lg font-medium text-white mb-3">Authentication Layer</h3> - <p class="text-gray-400 text-sm mb-3"> - Security is handled via <span class="text-white">Google Firebase Authentication</span>. We support: - </p> - <ul class="list-disc pl-5 space-y-2 text-sm text-gray-400"> - <li><strong>Google OAuth:</strong> One-click secure sign-in.</li> - <li><strong>Email/Password:</strong> Traditional credential access.</li> - </ul> - <p class="text-gray-400 text-sm mt-3"> - Upon login, a unique User ID (UID) is generated. This UID acts as the primary key for all database operations, ensuring you never access data belonging to another user. - </p> + <div class="p-6 rounded-xl bg-white/5 border border-white/10"> + <h3 class="text-white font-bold mb-2"><i class="fas fa-server text-lime-300 mr-2"></i> Backend (Server)</h3> + <ul class="text-sm text-neutral-400 space-y-2"> + <li>• <strong>Server:</strong> Python <code>aiohttp</code> (AsyncIO)</li> + <li>• <strong>Runtime:</strong> <code>subprocess</code> pipelines</li> + <li>• <strong>AI Engine:</strong> Google Gemini 2.5 Flash</li> + <li>• <strong>Database:</strong> Firebase Firestore (NoSQL)</li> + </ul> + </div> + </div> + </section> + + <!-- 02 Editor --> + <section id="editor" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">02.</span> Professional Editor Experience + </h2> + <p class="text-neutral-300 mb-4"> + Replaced the standard textarea with <strong>CodeMirror</strong> to provide an IDE-grade environment directly in the browser. + </p> + + <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> + <div class="p-4 border border-lime-300/20 bg-lime-300/5 rounded-lg"> + <h4 class="text-lime-300 font-bold mb-2">Visual & Editing</h4> + <ul class="text-xs text-neutral-300 space-y-1"> + <li>• <strong>Syntax Highlighting:</strong> Dracula theme for easy reading.</li> + <li>• <strong>Line Numbers:</strong> Essential for debugging.</li> + <li>• <strong>Bracket Matching:</strong> Visual cues for matching parentheses.</li> + <li>• <strong>Auto-Indent:</strong> Smart indentation for Python and C++.</li> + </ul> + </div> + <div class="p-4 border border-white/10 bg-white/5 rounded-lg"> + <h4 class="text-white font-bold mb-2">Developer Tools</h4> + <ul class="text-xs text-neutral-300 space-y-1"> + <li>• <strong>Undo/Redo:</strong> <code>Ctrl+Z</code> / <code>Ctrl+Y</code> support with history stack.</li> + <li>• <strong>Mobile Helper Bar:</strong> Sticky keys for <code>{ } [ ] ;</code> on touch devices.</li> + <li>• <strong>Export:</strong> Download code as <code>.py</code>, <code>.c</code>, or <code>.cpp</code> files.</li> + <li>• <strong>Clear Code:</strong> Quick reset with confirmation modal.</li> + </ul> + </div> + </div> + </section> + + <!-- 03 Communication --> + <section id="communication" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">03.</span> WebSocket I/O Protocol + </h2> + <p class="text-neutral-300 mb-4"> + Real-time interaction handles input/output streams efficiently. The server streams <code>stdout</code> characters immediately, preventing "hanging" on long-running processes. + </p> + + <div class="code-block"> + <pre><code class="language-json">// 1. Run Command (Client -> Server) +{ "type": "run", "language": "python", "code": "print('Hello')" } + +// 2. Output Stream (Server -> Client) +// Streamed character-by-character or line-by-line +{ "type": "stdout", "data": "H" } +{ "type": "stdout", "data": "e" } ... + +// 3. User Input (Client -> Server) +// Sent when user types in terminal +{ "type": "input", "data": "user_input\n" }</code></pre> + </div> + </section> + + <!-- 04 Engines --> + <section id="engines" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">04.</span> Execution Engines + </h2> + <p class="text-neutral-300 mb-6"> + Each language runs in a specialized, isolated subprocess on the backend. + </p> + + <div class="space-y-6"> + <div class="p-6 bg-white/5 rounded-xl border border-white/10"> + <div class="flex items-center gap-3 mb-4"> + <i class="fab fa-python text-2xl text-blue-400"></i> + <h3 class="text-xl font-bold text-white">Python 3 Engine</h3> </div> + <p class="text-sm text-neutral-400 mb-4"> + The Python environment runs on the latest stable <strong>Python 3</strong> release. + </p> + <ul class="list-disc list-inside text-sm text-neutral-300 space-y-1"> + <li><strong>Execution:</strong> Code is written to a temporary file and executed via `python3 -u` (unbuffered) to ensure real-time output.</li> + <li><strong>Pip Packages:</strong> The environment comes pre-configured with standard libraries. <code>pip</code> is available in the backend environment, allowing for pre-installed packages to be imported (e.g., math, time, random).</li> + <li><strong>Indentation:</strong> The editor converts Tabs to 4 Spaces automatically to prevent <code>IndentationError</code>.</li> + </ul> + </div> - <div> - <h3 class="text-lg font-medium text-white mb-3">Request Lifecycle</h3> - <ol class="list-decimal pl-5 space-y-4 text-sm text-gray-400"> - <li> - <strong class="text-white">Input Capture:</strong> The frontend captures your message, active code editor content, and any uploaded file context. - </li> - <li> - <strong class="text-white">Secure Transmission:</strong> Data is sent to our Python Flask backend (hosted on Render) over HTTPS, accompanied by your Firebase ID Token. - </li> - <li> - <strong class="text-white">Server-Side Verification:</strong> The backend validates your ID Token using the Firebase Admin SDK before processing any request. - </li> - <li> - <strong class="text-white">AI Processing:</strong> Validated requests are forwarded to the Gemini 2.5 API. The system prompt enforces a "Coding Assistant Only" persona. - </li> - <li> - <strong class="text-white">Response Streaming:</strong> The AI response is streamed back to your browser in real-time chunks, reducing perceived latency. - </li> - </ol> + <div class="p-6 bg-white/5 rounded-xl border border-white/10"> + <div class="flex items-center gap-3 mb-4"> + <i class="fas fa-microchip text-2xl text-blue-600"></i> + <h3 class="text-xl font-bold text-white">C / C++ Compiler</h3> </div> + <p class="text-sm text-neutral-400 mb-4"> + Powered by the <strong>GNU Compiler Collection (GCC)</strong>. + </p> + <ul class="list-disc list-inside text-sm text-neutral-300 space-y-1"> + <li><strong>C Language:</strong> Compiles via `gcc source.c -o app -lm -pthread`. Uses standard C11/C17 standards.</li> + <li><strong>C++ Language:</strong> Compiles via `g++ source.cpp -o app -lm -pthread`. Supports modern C++ standards.</li> + <li><strong>Extended Support:</strong> Explicitly links against the Math library (<code>-lm</code>) and Threads library (<code>-pthread</code>), enabling advanced mathematical operations and multi-threaded applications.</li> + <li><strong>Binary Execution:</strong> After compilation, the binary is immediately executed (`./app`), and output is piped to the WebSocket.</li> + <li><strong>Error Handling:</strong> Compilation errors (stderr) are captured and displayed in red in the terminal.</li> + </ul> </div> - </section> - - <!-- Section 3: Data & Privacy --> - <section id="data-privacy"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">3</span> - Data Storage & Privacy - </h2> - <p class="text-gray-300 mb-6"> - We use <span class="text-white">Google Cloud Firestore</span> (NoSQL) for persistence. Your data is structured to maximize privacy and ease of deletion. - </p> - <div class="grid md:grid-cols-2 gap-6 mb-6"> - <div class="bg-gemini-surface p-5 rounded-xl border border-gray-800"> - <h4 class="text-white font-medium mb-2">Data Structure</h4> - <code class="text-xs font-mono text-blue-300 block mb-2">/users/{userId}/chats/{chatId}</code> - <p class="text-xs text-gray-400">All your chats live exclusively under your user document. No data is stored in global collections.</p> + <!-- NEW PERFORMANCE BLOCK --> + <div class="p-6 bg-amber-500/5 rounded-xl border border-amber-500/20 mt-8"> + <div class="flex items-center gap-3 mb-4 text-amber-500"> + <i class="fas fa-tachometer-alt text-xl"></i> + <h3 class="text-lg font-bold">Performance Notes</h3> </div> - <div class="bg-gemini-surface p-5 rounded-xl border border-gray-800"> - <h4 class="text-white font-medium mb-2">Deletion Policy</h4> - <p class="text-xs text-gray-400 mb-2">You have full control over your data:</p> - <ul class="text-xs text-gray-400 list-disc pl-4 space-y-1"> - <li><strong>Single Chat:</strong> Instantly removed via the context menu.</li> - <li><strong>Clear History:</strong> A batch operation wipes your entire `/chats` subcollection.</li> + <div class="text-sm text-neutral-300 leading-relaxed space-y-4"> + <p> + This project is currently hosted on <strong>Render’s free tier</strong>, which utilizes automatic sleep cycles to conserve resources. This introduces specific behavior patterns: + </p> + <ul class="list-disc list-inside space-y-2 text-neutral-400"> + <li><strong>Cold Starts:</strong> The first execution after a period of inactivity may take several seconds due to the container waking up.</li> + <li><strong>Warm Execution:</strong> Subsequent runs happen in real-time and are significantly faster.</li> + <li><strong>CPU Limits:</strong> CPU-intensive Python benchmarks are not representative of real-world interactive usage on this deployment.</li> </ul> </div> </div> - </section> - - <!-- Section 4: Features Guide --> - <section id="features"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">4</span> - Key Features - </h2> - - <div class="space-y-6"> - <div class="group"> - <h3 class="text-lg font-medium text-white mb-2 group-hover:text-gemini-blue transition-colors">Smart Code Artifacts</h3> - <p class="text-sm text-gray-400"> - When Ada writes code, it automatically detects the language and extracts it into the dedicated <strong>Artifact Panel</strong> on the right. This keeps your chat clean and gives you a dedicated workspace to view, copy, or format the code. - </p> + + </div> + </section> + + <!-- 05 AI Auto-Debug --> + <section id="ai-debug" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">05.</span> AI Auto-Debug System + </h2> + <p class="text-neutral-300 mb-4"> + The compiler monitors the output stream for common error patterns (e.g., <code>Traceback</code>, <code>Segmentation fault</code>, <code>error:</code>). + </p> + <div class="bg-black/30 p-4 rounded-lg border-l-2 border-lime-300"> + <h4 class="text-sm font-bold text-white mb-2">How it works:</h4> + <ol class="list-decimal list-inside text-xs text-neutral-400 space-y-2"> + <li><strong>Capture:</strong> The client buffers the last 4KB of terminal output.</li> + <li><strong>Trigger:</strong> If an error keyword is found, the "Ask AI" button appears.</li> + <li><strong>Processing:</strong> Code + Error Log is sent to <strong>Gemini 2.5 Flash</strong>.</li> + <li><strong>Response:</strong> The AI generates a JSON object containing a plain-English explanation and the corrected code block.</li> + <li><strong>Patch:</strong> The user can review the fix in a modal and apply it to the editor instantly.</li> + </ol> + </div> + </section> + + <!-- 06 Persistence --> + <section id="persistence" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">06.</span> Sharing & Persistence + </h2> + <p class="text-neutral-300 mb-6"> + Data storage is handled in two distinct layers to balance privacy and collaboration. + </p> + + <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> + <div class="border border-white/10 rounded-xl p-5"> + <div class="flex items-center gap-2 mb-3 text-lime-300"> + <i class="fas fa-hdd"></i> + <h3 class="font-bold">Local Persistence</h3> </div> + <p class="text-xs text-neutral-400 leading-relaxed"> + Every keystroke is saved to the browser's <code>localStorage</code>. This data never leaves your device until you execute or share it. + </p> + </div> - <div class="group"> - <h3 class="text-lg font-medium text-white mb-2 group-hover:text-gemini-blue transition-colors">Chat Sharing</h3> - <p class="text-sm text-gray-400"> - Need to share a solution? You can generate a unique link for any chat conversation. - </p> - <ul class="list-disc pl-5 mt-2 space-y-1 text-sm text-gray-500"> - <li><strong>Public Access:</strong> Anyone with the link can view the conversation (Read-Only).</li> - <li><strong>Forking:</strong> If the viewer logs in, they can save a copy of the chat to their own history and continue the conversation.</li> - </ul> + <div class="border border-white/10 rounded-xl p-5"> + <div class="flex items-center gap-2 mb-3 text-lime-300"> + <i class="fas fa-share-alt"></i> + <h3 class="font-bold">Cloud Sharing</h3> </div> + <p class="text-xs text-neutral-400 leading-relaxed"> + Uploads a snapshot to <strong>Firebase</strong> generating a short 7-char ID (e.g., <code>?share=AbC123X</code>). + </p> + </div> - <div class="group"> - <h3 class="text-lg font-medium text-white mb-2 group-hover:text-gemini-blue transition-colors">Export Data</h3> - <p class="text-sm text-gray-400"> - You are not locked in. Export any chat session as a JSON file or Markdown document for your own records or documentation. - </p> + <div class="border border-white/10 rounded-xl p-5"> + <div class="flex items-center gap-2 mb-3 text-lime-300"> + <i class="fas fa-link"></i> + <h3 class="font-bold">Base64 / LZ Fallback</h3> </div> + <p class="text-xs text-neutral-400 leading-relaxed"> + Code can be encoded directly into the URL (e.g., <code>?code=...</code>). + <br><span class="text-lime-300/80 mt-2 block">Pro Tip: Use <strong>LZ-String</strong> compression to reduce URL length by ~60% vs standard Base64.</span> + </p> </div> - </section> - - <!-- Section 5: Contributing --> - <section id="contributing"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">5</span> - Contributing - </h2> - <p class="text-gray-300 mb-6"> - Ada AI is an open-source project licensed under MIT. We welcome pull requests, bug reports, and feature suggestions from the developer community. - </p> + </div> + </section> - <div class="bg-gemini-surface p-6 rounded-xl border border-gray-700"> - <h3 class="text-white font-medium mb-4">How to Contribute</h3> - <ol class="list-decimal pl-5 space-y-3 text-sm text-gray-300 mb-6"> - <li><strong>Fork the Repository:</strong> Go to our GitHub and click "Fork".</li> - <li><strong>Clone Locally:</strong> <code class="bg-black px-2 py-1 rounded text-gray-400 ml-2">git clone https://github.com/notamitgamer/ada-web.git</code></li> - <li><strong>Create Branch:</strong> <code class="bg-black px-2 py-1 rounded text-gray-400 ml-2">git checkout -b feature/amazing-feature</code></li> - <li><strong>Commit & Push:</strong> Make your changes and push to your fork.</li> - <li><strong>Pull Request:</strong> Open a PR describing your changes.</li> - </ol> - - <a href="https://github.com/notamitgamer/ada-web" target="_blank" class="inline-flex items-center justify-center w-full md:w-auto bg-white text-black px-6 py-3 rounded-lg font-bold hover:bg-gray-200 transition-colors"> - <svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg> - View on GitHub - </a> + <!-- 07 Lifecycle --> + <section id="lifecycle" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">07.</span> Data Lifecycle + </h2> + <div class="overflow-x-auto"> + <table class="w-full text-left text-sm text-neutral-400"> + <thead class="bg-white/5 text-white font-mono uppercase text-xs"> + <tr> + <th class="p-3">Stage</th> + <th class="p-3">Storage Location</th> + <th class="p-3">Duration</th> + <th class="p-3">Accessibility</th> + </tr> + </thead> + <tbody class="divide-y divide-white/5"> + <tr> + <td class="p-3 text-lime-300">Drafting</td> + <td class="p-3">Browser LocalStorage</td> + <td class="p-3">Persistent (User Control)</td> + <td class="p-3">Private (Device Only)</td> + </tr> + <tr> + <td class="p-3 text-lime-300">Execution</td> + <td class="p-3">Server RAM / Temp File</td> + <td class="p-3">Ephemeral (Seconds)</td> + <td class="p-3">System (Deleted after run)</td> + </tr> + <tr> + <td class="p-3 text-lime-300">Sharing</td> + <td class="p-3">Firebase Firestore</td> + <td class="p-3">Permanent</td> + <td class="p-3">Public (Link Holders)</td> + </tr> + </tbody> + </table> + </div> + </section> + + <!-- 08 Security --> + <section id="security" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">08.</span> Security Implementation + </h2> + <p class="text-neutral-300 mb-4"> + Security is enforced at the environment level to prevent abuse. + </p> + <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> + <div class="p-4 border border-white/10 bg-white/5 rounded-lg"> + <h4 class="text-white font-bold mb-2">Sanitized Environment</h4> + <p class="text-xs text-neutral-400"> + Subprocesses run with a stripped environment (`safe_env`). API keys, system paths, and sensitive variables are removed from the execution context. + </p> </div> - </section> - - <!-- Section 6: Support --> - <section id="support"> - <h2 class="text-2xl font-semibold text-white mb-6 flex items-center"> - <span class="bg-gemini-surface w-8 h-8 rounded-full flex items-center justify-center text-sm mr-3 border border-gray-700">6</span> - Support & Contact - </h2> - <p class="text-gray-300 mb-6">Found a bug? Need a feature? Or just want to say hi? Here is how you can reach the developer.</p> - - <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> - <a href="mailto:amitdutta4255@gmail.com" class="group p-6 bg-gemini-surface border border-gray-800 rounded-xl hover:border-red-500/50 transition-all"> - <div class="flex items-center mb-2"> - <span class="w-2 h-2 rounded-full bg-red-500 mr-2"></span> - <h4 class="text-white font-medium group-hover:text-red-400">Critical Support</h4> - </div> - <p class="text-sm text-gray-400 mb-4">For urgent issues, security vulnerabilities, or major bugs.</p> - <span class="text-xs font-mono text-gray-500">amitdutta4255@gmail.com</span> - </a> + <div class="p-4 border border-white/10 bg-white/5 rounded-lg"> + <h4 class="text-white font-bold mb-2">Session Isolation</h4> + <p class="text-xs text-neutral-400"> + Each client connection generates a unique <strong>UUID-based session directory</strong> (e.g., `temp_sessions/abc-123`). All temporary files are created within this isolated sandbox and are automatically wiped upon disconnection, preventing data leakage between concurrent users. + </p> + </div> + </div> + </section> + + <!-- 09 Developer / Contribution --> + <section id="contribution" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">09.</span> Developers & Contribution + </h2> + <p class="text-neutral-300 mb-6"> + We welcome contributions from the community. Whether you've found a bug, want to suggest a feature, or add support for a new language, here is how you can get involved. + </p> - <a href="mailto:mail@amit.is-a.dev" class="group p-6 bg-gemini-surface border border-gray-800 rounded-xl hover:border-gemini-blue transition-all"> - <div class="flex items-center mb-2"> - <span class="w-2 h-2 rounded-full bg-blue-500 mr-2"></span> - <h4 class="text-white font-medium group-hover:text-gemini-blue">General Inquiries</h4> - </div> - <p class="text-sm text-gray-400 mb-4">For feedback, feature requests, or general questions.</p> - <span class="text-xs font-mono text-gray-500">mail@amit.is-a.dev</span> + <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8"> + <!-- Open Source Card --> + <div class="p-6 bg-white/5 rounded-xl border border-white/10 hover:border-lime-300/50 transition-colors group"> + <i class="fab fa-github text-3xl text-white group-hover:text-lime-300 mb-4 transition-colors"></i> + <h3 class="text-xl font-bold text-white mb-2">Open Source</h3> + <p class="text-sm text-neutral-400 mb-6"> + The core infrastructure is open-source. Clone the repo, create a branch, and submit a Pull Request. + </p> + <div class="flex gap-3"> + <a href="https://github.com/notamitgamer/cloud-compiler/issues" target="_blank" class="px-3 py-1.5 rounded bg-white/10 text-xs font-mono hover:bg-white/20 transition-colors border border-white/10"> + <i class="fas fa-bug mr-1"></i> Report Bug + </a> + <a href="https://github.com/notamitgamer/cloud-compiler" target="_blank" class="px-3 py-1.5 rounded bg-lime-300/10 text-lime-300 text-xs font-mono hover:bg-lime-300/20 transition-colors border border-lime-300/20"> + <i class="fas fa-code-branch mr-1"></i> Fork Repo + </a> + </div> + </div> + + <!-- Contact Card --> + <div class="p-6 bg-white/5 rounded-xl border border-white/10"> + <i class="fas fa-envelope-open-text text-3xl text-white mb-4"></i> + <h3 class="text-xl font-bold text-white mb-2">Direct Contact</h3> + <p class="text-sm text-neutral-400 mb-6"> + For security vulnerabilities, private feedback, or collaboration inquiries, please email directly. + </p> + <a href="mailto:amitdutta4255@gmail.com" class="text-lime-300 font-mono text-sm hover:underline flex items-center gap-2"> + <i class="fas fa-at"></i> amitdutta4255@gmail.com </a> </div> - </section> + </div> + </section> - </div> - </div> + <!-- 10 Disclaimer --> + <section id="disclaimer" class="doc-section"> + <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center"> + <span class="mr-3 text-neutral-600">10.</span> Legal & Disclaimer + </h2> + <div class="p-6 rounded-xl border border-red-500/20 bg-red-500/5"> + <p class="text-neutral-300 mb-4"> + This compiler infrastructure utilizes Google's Generative AI services and Firebase for data storage. + </p> + <ul class="text-lime-300 font-mono text-sm mb-6 space-y-1"> + <li><i class="fas fa-envelope mr-2"></i> <a href="mailto:amitdutta4255@gmail.com" class="hover:underline">amitdutta4255@gmail.com</a></li> + <li><i class="fas fa-envelope mr-2"></i> <a href="mailto:mail@amit.is-a.dev" class="hover:underline">mail@amit.is-a.dev</a></li> + <li><i class="fab fa-github mr-2"></i> <a href="https://github.com/notamitgamer" target="_blank" class="hover:underline">@notamitgamer</a></li> + </ul> + <div class="text-neutral-400 text-sm border-t border-white/10 pt-4 leading-relaxed"> + <p class="mb-4"><strong class="text-red-400 uppercase">Disclaimer of Liability:</strong> This tool is provided "as is". Amit Dutta assumes no responsibility or liability for any consequences, errors, or data loss arising from the use of this compiler. This project is provided for demonstration purposes only.</p> + + <p class="italic font-mono text-xs opacity-80 bg-black/20 p-3 border border-red-500/20 rounded"> + "I explicitly disclaim any affiliation with or responsibility for the ongoing operation of this project. I reserve the absolute right to modify, suspend, or permanently delete this compiler and its associated services at any time, for any reason, without prior notice." + </p> + </div> + </div> + </section> - <footer class="mt-20 pt-8 border-t border-gray-800 text-center"> - <p class="text-sm text-gray-500">&copy; 2026 Ada AI. All rights reserved.</p> - <div class="mt-2 space-x-4"> - <a href="/terms.html" class="text-xs text-gray-600 hover:text-gray-300 transition-colors">Terms & Conditions</a> - <a href="https://github.com/notamitgamer/ada-web" class="text-xs text-gray-600 hover:text-gray-300 transition-colors">GitHub</a> - </div> - </footer> + </main> </div> + + <script> + hljs.highlightAll(); + + // Simple scroll spy for nav + window.addEventListener('scroll', () => { + const sections = document.querySelectorAll('.doc-section'); + const navLinks = document.querySelectorAll('.nav-link'); + + let current = ''; + sections.forEach(section => { + const sectionTop = section.offsetTop; + if (pageYOffset >= sectionTop - 150) { + current = section.getAttribute('id'); + } + }); + + navLinks.forEach(link => { + link.classList.remove('active'); + if (link.getAttribute('href').includes(current)) { + link.classList.add('active'); + } + }); + }); + </script> </body> </html> \ No newline at end of file diff --git a/docs/index.html b/docs/index.html @@ -1,1643 +1,373 @@ <!DOCTYPE html> -<html lang="en" class="dark"> +<html lang="en" class="scroll-smooth"> <head> <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> - <title>Ada AI</title> -<link rel="icon" type="image/png" href="logo.png"> - + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="google-site-verification" content="pwteHw44Ax3N2B1zkFzVJB7NIK0-xgQGRihK_vtZTF4" /> + <title>Cloud Code Compiler // Amit Dutta</title> + <link rel="canonical" href="https://compiler.amit.is-a.dev/" /> + <link rel="icon" type="image/x-icon" href="https://compiler.amit.is-a.dev/logo.png"> + + <!-- Fonts --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet"> - <!-- Tailwind CSS --> + <!-- Libraries --> + <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> <script src="https://cdn.tailwindcss.com"></script> - <script> - tailwind.config = { - darkMode: 'class', - theme: { - extend: { - colors: { - gemini: { - bg: '#131314', // Deepest charcoal - surface: '#1E1F20', // Sidebar/Panels - surfaceHover: '#28292A', - accent: '#444746', // Borders/Icons - text: '#E3E3E3', // Primary text - textSecondary: '#C4C7C5', - blue: '#A8C7FA', // Google Blue - purple: '#D0BCFF' // Google Purple - } - }, - fontFamily: { - sans: ['Inter', 'sans-serif'], - mono: ['JetBrains Mono', 'monospace'], - }, - animation: { - 'fade-in': 'fadeIn 0.4s ease-out forwards', - 'slide-up': 'slideUp 0.5s cubic-bezier(0.2, 0.0, 0, 1.0) forwards', - 'spin-slow-entry': 'spinSlowEntry 1.2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards', - }, - keyframes: { - fadeIn: { - '0%': { opacity: '0' }, - '100%': { opacity: '1' }, - }, - slideUp: { - '0%': { opacity: '0', transform: 'translateY(20px)' }, - '100%': { opacity: '1', transform: 'translateY(0)' }, - }, - spinSlowEntry: { - '0%': { opacity: '0', transform: 'rotate(-180deg) scale(0.5)' }, - '100%': { opacity: '1', transform: 'rotate(0deg) scale(1)' } - } - } - } - } - } - </script> - - <!-- Google Fonts --> - <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> - <!-- Icons --> - <script src="https://unpkg.com/lucide@latest"></script> - <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> - - <!-- CodeMirror (Editor) --> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css"> - <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/javascript/javascript.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/python/python.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/xml/xml.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/css/css.min.js"></script> - - <!-- Firebase SDKs --> - <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js"></script> - <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-auth-compat.js"></script> - <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore-compat.js"></script> - <style> - body { - background-color: #131314; - color: #E3E3E3; - font-family: 'Inter', sans-serif; - overflow: hidden; - -webkit-font-smoothing: antialiased; + :root { + --bg-main: #050505; + --accent: #bef264; /* Lime 300 */ + --text-muted: #737373; + --border-color: rgba(255, 255, 255, 0.1); } - /* Custom Scrollbar */ - ::-webkit-scrollbar { width: 6px; height: 6px; } - ::-webkit-scrollbar-track { background: transparent; } - ::-webkit-scrollbar-thumb { background: #444746; border-radius: 3px; } - ::-webkit-scrollbar-thumb:hover { background: #5E5E5E; } - - /* Prose / Markdown Styles */ - .prose p { margin-bottom: 0.8rem; line-height: 1.6; color: #E3E3E3; font-weight: 300; } - .prose strong { color: #fff; font-weight: 600; } - .prose ul { list-style-type: disc; padding-left: 1.5rem; margin-bottom: 1rem; } - .prose ol { list-style-type: decimal; padding-left: 1.5rem; margin-bottom: 1rem; } - .prose code { - font-family: 'JetBrains Mono', monospace; - background: #28292A; - padding: 2px 6px; - border-radius: 4px; - color: #A8C7FA; - font-size: 0.85em; - } - .prose pre { display: none; } /* Hidden in chat, shown in Artifact Panel */ - .prose h1, .prose h2, .prose h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-weight: 500; color: white; } - .prose a { color: #A8C7FA; text-decoration: none; } - .prose a:hover { text-decoration: underline; } - - /* Message Bubbles */ - .msg-user { - background-color: #28292A; - color: #E3E3E3; - border-radius: 20px; - padding: 12px 20px; - max-width: 80%; - font-weight: 400; - } - .msg-ai { - background: transparent; - color: #E3E3E3; - padding: 0; - max-width: 100%; - } - - /* Code Block Card in Chat */ - .code-card { - background: #1E1F20; - border: 1px solid #444746; - border-radius: 12px; - overflow: hidden; - margin: 1rem 0; - transition: all 0.2s; - cursor: pointer; - position: relative; - } - .code-card:hover { - border-color: #A8C7FA; - transform: translateY(-1px); - } - - /* CodeMirror Customization */ - .CodeMirror { - height: 100% !important; - font-family: 'JetBrains Mono', monospace; - font-size: 14px; - background-color: #1e1e1e !important; - } - .cm-s-dracula.CodeMirror { - background-color: #1e1e1e !important; - } - - /* Typing Indicator */ - .typing-dot { - width: 6px; height: 6px; - background: #E3E3E3; - border-radius: 50%; - animation: bounce 1.4s infinite ease-in-out both; + body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-main); + color: #f5f5f5; + overflow-x: hidden; } - .typing-dot:nth-child(1) { animation-delay: -0.32s; } - .typing-dot:nth-child(2) { animation-delay: -0.16s; } - @keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } } - - /* Mobile Height Fix */ - .mobile-height { height: 100vh; height: calc(var(--vh, 1vh) * 100); } - /* Hide Scrollbar for Inputs */ - .no-scrollbar::-webkit-scrollbar { display: none; } - .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } - - /* Drawer Transitions */ - .drawer { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + /* Portfolio Aesthetic */ + .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-heading { font-family: 'Space Grotesk', sans-serif; } - /* Custom Ada Icon Animation */ - .ada-icon path { transform-origin: center; } - - /* Context Menu */ - .context-menu { - position: fixed; /* Changed from absolute to fixed for better mobile handling */ - background: #28292A; - border: 1px solid #444746; - border-radius: 12px; /* Slightly more rounded */ - padding: 4px; - z-index: 9999; - box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.1); - min-width: 180px; - animation: menuFadeIn 0.15s ease-out; - } - @keyframes menuFadeIn { - from { opacity: 0; transform: scale(0.95); } - to { opacity: 1; transform: scale(1); } - } - .context-menu-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 16px; /* Larger tap targets for mobile */ - cursor: pointer; - border-radius: 8px; - color: #E3E3E3; - font-size: 14px; - transition: background 0.2s; - } - .context-menu-item:hover { - background: #3C4043; - } - .context-menu-item.danger { color: #ff8b8b; } - .context-menu-item.danger:hover { background: rgba(255, 139, 139, 0.1); } - - /* Custom Switch (From Uiverse.io by Galahhad) */ - .switch { - /* switch */ - --switch-width: 46px; - --switch-height: 24px; - --switch-bg: rgb(68, 71, 70); - --switch-checked-bg: #A8C7FA; - --switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2); - --switch-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51); - /* circle */ - --circle-diameter: 18px; - --circle-bg: #fff; - --circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45); - --circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45); - --circle-transition: var(--switch-transition); - /* icon */ - --icon-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51); - --icon-cross-color: var(--switch-bg); - --icon-cross-size: 6px; - --icon-checkmark-color: var(--switch-checked-bg); - --icon-checkmark-size: 10px; - /* effect line */ - --effect-width: calc(var(--circle-diameter) / 2); - --effect-height: calc(var(--effect-width) / 2 - 1px); - --effect-bg: var(--circle-bg); - --effect-border-radius: 1px; - --effect-transition: all .2s ease-in-out; - - display: inline-block; + /* Noise Overlay */ + .bg-noise { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; z-index: 0; opacity: 0.03; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + } + + /* CRT Scanline */ + .crt-scanline { + position: fixed; top: 0; left: 0; width: 100%; height: 2px; + background: rgba(190, 242, 100, 0.1); opacity: 0.5; + pointer-events: none; z-index: 50; + animation: scanline 8s linear infinite; + } + @keyframes scanline { 0% { top: -10vh; } 100% { top: 110vh; } } + + /* Compiler Card Styling */ + .compiler-card { + background: rgba(255, 255, 255, 0.02); + border: 1px solid var(--border-color); + border-radius: 1.5rem; position: relative; + overflow: hidden; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + z-index: 10; } - .switch input { display: none; } + .compiler-card:hover { + transform: translateY(-5px); + border-color: var(--accent); + box-shadow: 0 0 20px rgba(190, 242, 100, 0.1); + } - .switch svg { - -webkit-transition: var(--icon-transition); - -o-transition: var(--icon-transition); - transition: var(--icon-transition); + .compiler-card::before { + content: ''; position: absolute; - height: auto; + inset: 0; + background: radial-gradient(800px circle at var(--mouse-x) var(--mouse-y), rgba(255, 255, 255, 0.06), transparent 40%); + opacity: 0; + transition: opacity 0.5s; + pointer-events: none; } - .switch .checkmark { - width: var(--icon-checkmark-size); - color: var(--icon-checkmark-color); - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); + .compiler-card:hover::before { + opacity: 1; } - .switch .cross { - width: var(--icon-cross-size); - color: var(--icon-cross-color); + .icon-container { + background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--border-color); + transition: all 0.3s ease; } - .slider { - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: var(--switch-width); - height: var(--switch-height); - background: var(--switch-bg); - border-radius: 999px; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - position: relative; - -webkit-transition: var(--switch-transition); - -o-transition: var(--switch-transition); - transition: var(--switch-transition); - cursor: pointer; + .compiler-card:hover .icon-container { + border-color: var(--accent); + background: rgba(190, 242, 100, 0.1); } - .circle { - width: var(--circle-diameter); - height: var(--circle-diameter); - background: var(--circle-bg); - border-radius: inherit; - -webkit-box-shadow: var(--circle-shadow); - box-shadow: var(--circle-shadow); - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-transition: var(--circle-transition); - -o-transition: var(--circle-transition); - transition: var(--circle-transition); - z-index: 1; - position: absolute; - left: var(--switch-offset); + /* Feature Card (Smaller) */ + .feature-card { + background: rgba(255, 255, 255, 0.02); + border: 1px solid var(--border-color); + border-radius: 1rem; + padding: 1.5rem; + transition: all 0.3s; + } + .feature-card:hover { + background: rgba(255, 255, 255, 0.04); + border-color: rgba(190, 242, 100, 0.3); } - .slider::before { - content: ""; + /* Animations */ + .floating-code { position: absolute; - width: var(--effect-width); - height: var(--effect-height); - left: calc(var(--switch-offset) + (var(--effect-width) / 2)); - background: var(--effect-bg); - border-radius: var(--effect-border-radius); - -webkit-transition: var(--effect-transition); - -o-transition: var(--effect-transition); - transition: var(--effect-transition); + font-family: 'JetBrains Mono', monospace; + font-size: 0.8rem; + color: var(--text-muted); + opacity: 0.2; + pointer-events: none; + animation: float 10s infinite ease-in-out; } - - .switch input:checked+.slider { - background: var(--switch-checked-bg); + @keyframes float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-20px); } } - .switch input:checked+.slider .checkmark { - -webkit-transform: scale(1); - -ms-transform: scale(1); - transform: scale(1); + /* Social Links */ + .social-link { + background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--border-color); + color: #a3a3a3; + transition: all 0.3s ease; } - - .switch input:checked+.slider .cross { - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); + .social-link:hover { + color: var(--accent); + border-color: var(--accent); + transform: translateY(-3px); } - .switch input:checked+.slider::before { - left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset)); - } - - .switch input:checked+.slider .circle { - left: calc(100% - var(--circle-diameter) - var(--switch-offset)); - -webkit-box-shadow: var(--circle-checked-shadow); - box-shadow: var(--circle-checked-shadow); + ::selection { background: var(--accent); color: black; } + + .typewriter h1 { border-right: none; } + + .fade-in-create { + animation: fadeIn 1s ease-in forwards; + opacity: 0; } + @keyframes fadeIn { to { opacity: 1; } } </style> </head> -<body class="mobile-height flex text-sm selection:bg-gemini-blue selection:text-black bg-gemini-bg"> +<body class="antialiased selection:bg-lime-300 selection:text-black"> - <!-- SVG Definitions --> - <svg style="display: none;"> - <symbol id="icon-ada" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <defs> - <linearGradient id="ada-gradient" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse"> - <stop offset="0%" stop-color="#4facfe" /> - <stop offset="50%" stop-color="#00f2fe" /> - <stop offset="100%" stop-color="#a8c7fa" /> - </linearGradient> - </defs> - <path d="M12 2L14.4 9.6L22 12L14.4 14.4L12 22L9.6 14.4L2 12L9.6 9.6L12 2Z" fill="url(#ada-gradient)" /> - <path d="M12 6L13.2 10.8L18 12L13.2 13.2L12 18L10.8 13.2L6 12L10.8 10.8L12 6Z" fill="white" fill-opacity="0.3" /> - </symbol> - </svg> + <div class="bg-noise"></div> + <div class="crt-scanline"></div> - <!-- Full Screen Loading/Verifying Overlay --> - <div id="loading-overlay" class="fixed inset-0 z-[200] flex flex-col items-center justify-center bg-[#131314] transition-opacity duration-500"> - <div class="w-16 h-16 mb-4 relative"> - <div class="absolute inset-0 bg-blue-500/20 blur-xl rounded-full"></div> - <svg class="w-full h-full animate-spin-slow-entry"><use href="#icon-ada"></use></svg> - </div> - <p class="text-gemini-textSecondary text-sm font-medium animate-pulse">Verifying Identity...</p> + <!-- Background Elements --> + <div class="fixed inset-0 z-0 overflow-hidden pointer-events-none"> + <div class="floating-code" style="top: 15%; left: 10%; animation-delay: 0s;">print("Hello World")</div> + <div class="floating-code" style="top: 25%; right: 15%; animation-delay: 2s;">#include &lt;stdio.h&gt;</div> + <div class="floating-code" style="bottom: 20%; left: 20%; animation-delay: 4s;">std::cout << "Code";</div> + <div class="floating-code" style="bottom: 30%; right: 10%; animation-delay: 1s;">const int MAX = 100;</div> </div> - <!-- Confirm Dialog --> - <div id="confirm-modal" class="fixed inset-0 z-[210] flex items-center justify-center bg-black/70 backdrop-blur-sm hidden opacity-0 transition-opacity"> - <div class="bg-gemini-surface p-6 rounded-2xl w-full max-w-sm border border-gemini-surfaceHover transform scale-95 transition-transform" id="confirm-modal-content"> - <h3 class="text-lg font-semibold text-white mb-2" id="confirm-title">Confirm</h3> - <p class="text-gemini-textSecondary text-sm mb-4" id="confirm-message">Are you sure?</p> - - <div id="confirm-input-container" class="hidden mb-4"> - <label class="block text-xs text-gemini-textSecondary mb-1">Type <span class="font-mono text-white select-all" id="confirm-match-text"></span> to confirm:</label> - <input type="text" id="confirm-input" class="w-full bg-[#131314] border border-gemini-surfaceHover rounded-lg p-2 text-white text-sm focus:outline-none focus:border-gemini-blue" placeholder=""> - </div> - - <div class="flex justify-end gap-3"> - <button onclick="closeConfirmModal()" class="px-4 py-2 rounded-lg text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover transition-colors">Cancel</button> - <button id="confirm-action-btn" class="px-4 py-2 rounded-lg bg-red-500/10 text-red-400 hover:bg-red-500/20 transition-colors font-medium">Confirm</button> + <!-- Hero Section --> + <div class="relative min-h-screen flex flex-col items-center justify-center p-6 z-10"> + + <header class="text-center mb-16" data-aos="fade-up"> + <div class="inline-block mb-4 px-4 py-1 rounded-full border border-white/10 bg-white/5 backdrop-blur-sm"> + <span class="text-xs font-mono text-lime-300 tracking-wider">/// V2.0 SYSTEM ONLINE</span> </div> - </div> - </div> - - <!-- Toast Notification (Custom Popups) --> - <div id="toast" class="fixed bottom-24 md:bottom-10 left-1/2 -translate-x-1/2 bg-gemini-surface border border-gemini-surfaceHover text-white px-6 py-3 rounded-full shadow-2xl z-[220] transition-all duration-300 transform translate-y-20 opacity-0 pointer-events-none flex items-center gap-2"> - <i data-lucide="info" class="w-4 h-4 text-gemini-blue"></i> - <span id="toast-message" class="text-sm font-medium">Notification</span> - </div> - - <!-- Auth Modal --> - <div id="auth-modal" class="fixed inset-0 z-[100] flex items-center justify-center bg-[#131314] transition-opacity duration-300 hidden opacity-0 pointer-events-none"> - <div class="w-full max-w-md p-8 text-center"> - <div class="mx-auto w-20 h-20 mb-6 rounded-full bg-gemini-surface flex items-center justify-center relative overflow-hidden group"> - <div class="absolute inset-0 bg-gradient-to-tr from-blue-500/20 to-purple-500/20 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> - <svg class="w-10 h-10 animate-spin-slow-entry drop-shadow-lg"><use href="#icon-ada"></use></svg> + <div class="typewriter max-w-4xl mx-auto"> + <h1 class="text-4xl sm:text-6xl md:text-7xl font-heading font-bold text-white mb-6 tracking-tight leading-tight"> + <span id="type-text"></span><br /> + <span id="create-text" class="text-lime-300 fade-in-create hidden">Execute.</span> + </h1> </div> - <h1 class="text-3xl font-medium text-white mb-3">Welcome to Ada</h1> - <p class="text-gemini-textSecondary mb-10">Sign in to access your coding workspace.</p> - - <button onclick="signInWithGoogle()" class="w-full bg-white text-[#131314] hover:bg-gray-100 font-medium py-3 px-6 rounded-full flex items-center justify-center gap-3 transition-colors"> - <img src="https://www.google.com/favicon.ico" class="w-5 h-5" alt="G"> - <span>Continue with Google</span> - </button> - </div> - </div> + <p class="sub-text-fade opacity-0 text-base sm:text-lg md:text-xl text-gray-400 max-w-3xl mx-auto leading-relaxed mt-4 font-light"> + Professional-grade remote execution. Now with AI debugging, local auto-save, and CodeMirror editor integration. + </p> + </header> - <!-- Profile Modal --> - <div id="profile-modal" onclick="toggleProfileModal()" class="fixed inset-0 z-[110] flex items-center justify-center bg-black/60 backdrop-blur-sm transition-opacity duration-300 hidden opacity-0 pointer-events-none"> - <div onclick="event.stopPropagation()" class="w-full max-w-sm bg-gemini-surface p-6 rounded-2xl shadow-2xl border border-gemini-surfaceHover transform scale-95 transition-transform duration-300" id="profile-modal-content"> - <div class="flex flex-col items-center"> - <div class="w-20 h-20 rounded-full bg-gradient-to-tr from-blue-500 to-purple-500 flex items-center justify-center text-2xl font-bold text-white mb-4 overflow-hidden border-4 border-gemini-surfaceHover relative shadow-lg"> - <img id="profile-avatar" class="w-full h-full object-cover hidden" src="" alt="User"> - <span id="profile-initial">U</span> - </div> - <h2 id="profile-name" class="text-xl font-semibold text-white">User Name</h2> - <p id="profile-email" class="text-sm text-gemini-textSecondary mb-6 break-all text-center">user@example.com</p> + <!-- Compiler Cards --> + <main class="w-full max-w-6xl mx-auto px-4" data-aos="fade-up" data-aos-delay="200"> + <div class="grid grid-cols-1 md:grid-cols-3 gap-6" id="compiler-grid"> - <div class="w-full grid grid-cols-2 gap-3 mb-6"> - <div class="bg-gemini-bg p-3 rounded-xl border border-gemini-surfaceHover text-center"> - <span class="block text-xs text-gemini-textSecondary uppercase tracking-wider mb-1">Status</span> - <span class="text-sm text-white font-medium">Free</span> - </div> - <div class="bg-gemini-bg p-3 rounded-xl border border-gemini-surfaceHover text-center"> - <span class="block text-xs text-gemini-textSecondary uppercase tracking-wider mb-1">Joined</span> - <span class="text-sm text-white font-medium">Jan '26</span> - </div> - </div> - - <button onclick="confirmSignOut()" class="w-full bg-[#3C4043] hover:bg-[#494c50] text-white py-2.5 rounded-full flex items-center justify-center gap-2 transition-colors font-medium"> - <i data-lucide="log-out" class="w-4 h-4"></i> - Sign Out - </button> - </div> - </div> - </div> - - <!-- Settings Modal --> - <div id="settings-modal" onclick="toggleSettingsModal()" class="fixed inset-0 z-[110] flex items-center justify-center bg-black/60 backdrop-blur-sm transition-opacity duration-300 hidden opacity-0 pointer-events-none"> - <div onclick="event.stopPropagation()" class="w-full max-w-md bg-gemini-surface p-6 rounded-2xl shadow-2xl border border-gemini-surfaceHover transform scale-95 transition-transform duration-300 max-h-[85vh] overflow-y-auto" id="settings-modal-content"> - <div class="flex items-center justify-between mb-6 border-b border-gemini-surfaceHover pb-4"> - <h2 class="text-xl font-semibold text-white">Settings</h2> - <button onclick="toggleSettingsModal()" class="text-gemini-textSecondary hover:text-white p-1 rounded-full hover:bg-gemini-surfaceHover transition-colors"> - <i data-lucide="x" class="w-5 h-5"></i> - </button> - </div> - - <div class="space-y-2"> - <!-- Chat Sharing --> - <div class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center justify-between group"> - <div class="flex items-center gap-3"> - <div class="p-2 bg-purple-500/10 rounded-lg text-purple-400 group-hover:bg-purple-500/20"><i data-lucide="share-2" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Chat Sharing</h3> - <p class="text-xs text-gemini-textSecondary">Allow public links</p> - </div> - </div> - <!-- Custom Toggle UI --> - <label class="switch"> - <input type="checkbox" id="share-toggle-checkbox" onchange="toggleShareSetting(this)"> - <div class="slider"> - <div class="circle"> - <svg class="cross" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 365.696 365.696" y="0" x="0" height="6" width="6" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg"> - <g> - <path data-original="#000000" fill="currentColor" d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"></path> - </g> - </svg> - <svg class="checkmark" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 24 24" y="0" x="0" height="10" width="10" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg"> - <g> - <path class="" data-original="#000000" fill="currentColor" d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"></path> - </g> - </svg> - </div> - </div> - </label> - </div> - - <!-- Font Size --> - <div class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors flex items-center justify-between group"> - <div class="flex items-center gap-3"> - <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="type" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Font Size</h3> - <p class="text-xs text-gemini-textSecondary">Adjust readability</p> - </div> - </div> - <div class="flex items-center gap-2 bg-gemini-bg p-1 rounded-lg border border-gemini-surfaceHover"> - <button onclick="changeFontSize(-1)" class="p-1 hover:bg-gemini-surfaceHover rounded text-gemini-textSecondary hover:text-white"><i data-lucide="minus" class="w-3 h-3"></i></button> - <span id="font-size-display" class="text-xs font-mono w-4 text-center">14</span> - <button onclick="changeFontSize(1)" class="p-1 hover:bg-gemini-surfaceHover rounded text-gemini-textSecondary hover:text-white"><i data-lucide="plus" class="w-3 h-3"></i></button> - </div> - </div> - - <div class="h-px bg-gemini-surfaceHover my-2"></div> - - <!-- Help & Support --> - <a href="https://github.com/notamitgamer/ada-web/issues" target="_blank" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-green-500/10 rounded-lg text-green-400 group-hover:bg-green-500/20"><i data-lucide="help-circle" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Help & Support</h3> - <p class="text-xs text-gemini-textSecondary">Report bugs or request features</p> + <!-- C Compiler --> + <a href="./c.html" class="compiler-card p-8 group block"> + <div class="icon-container w-14 h-14 rounded-xl flex items-center justify-center mb-6"> + <span class="font-heading font-bold text-2xl text-white">C</span> </div> - <i data-lucide="external-link" class="w-4 h-4 text-gemini-textSecondary ml-auto"></i> - </a> - - <!-- Contribute --> - <a href="https://github.com/notamitgamer/ada-web" target="_blank" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-orange-500/10 rounded-lg text-orange-400 group-hover:bg-orange-500/20"><i data-lucide="git-branch" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Contribute</h3> - <p class="text-xs text-gemini-textSecondary">Fork repo & submit PRs</p> + <h2 class="text-2xl font-heading font-bold text-white mb-2 group-hover:text-lime-300 transition-colors">Standard C</h2> + <p class="text-sm text-neutral-500 mb-6 leading-relaxed"> + Compile standard C programs via GCC. Now supports <strong>math libraries</strong> and <strong>multi-threading</strong> out of the box. + </p> + <div class="flex items-center text-xs font-mono text-lime-300 uppercase tracking-widest"> + Launch <i class="fas fa-arrow-right ml-2 group-hover:translate-x-1 transition-transform"></i> </div> - <i data-lucide="external-link" class="w-4 h-4 text-gemini-textSecondary ml-auto"></i> </a> - <!-- Developer Contact --> - <a href="mailto:amitdutta4255@gmail.com?subject=Ada%20AI%20Critical%20Support" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-red-500/10 rounded-lg text-red-400 group-hover:bg-red-500/20"><i data-lucide="alert-circle" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Critical Support</h3> - <p class="text-xs text-gemini-textSecondary">Contact developer directly</p> + <!-- C++ Compiler --> + <a href="./cpp.html" class="compiler-card p-8 group block"> + <div class="icon-container w-14 h-14 rounded-xl flex items-center justify-center mb-6"> + <span class="font-heading font-bold text-2xl text-white">C++</span> </div> - </a> - - <!-- General Feedback --> - <a href="mailto:mail@amit.is-a.dev?subject=Ada%20AI%20Feedback" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-yellow-500/10 rounded-lg text-yellow-400 group-hover:bg-yellow-500/20"><i data-lucide="message-square" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Send Feedback</h3> - <p class="text-xs text-gemini-textSecondary">Suggestions & improvements</p> + <h2 class="text-2xl font-heading font-bold text-white mb-2 group-hover:text-lime-300 transition-colors">Modern C++</h2> + <p class="text-sm text-neutral-500 mb-6 leading-relaxed"> + Execute C++ code via G++. Features standard STL support, <strong>math</strong>, and <strong>threading</strong> capabilities. + </p> + <div class="flex items-center text-xs font-mono text-lime-300 uppercase tracking-widest"> + Launch <i class="fas fa-arrow-right ml-2 group-hover:translate-x-1 transition-transform"></i> </div> </a> - <div class="h-px bg-gemini-surfaceHover my-2"></div> - - <!-- Terms --> - <a href="/terms.html" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="file-text" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Terms & Conditions</h3> - <p class="text-xs text-gemini-textSecondary">Usage policies</p> + <!-- Python Compiler --> + <a href="./python.html" class="compiler-card p-8 group block"> + <div class="icon-container w-14 h-14 rounded-xl flex items-center justify-center mb-6"> + <i class="fab fa-python text-2xl text-white"></i> </div> - </a> - <!-- Docs --> - <a href="/docs.html" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group"> - <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="file-text" class="w-4 h-4"></i></div> - <div> - <h3 class="text-white text-sm font-medium">Docs</h3> - <p class="text-xs text-gemini-textSecondary">Service Documentation</p> + <h2 class="text-2xl font-heading font-bold text-white mb-2 group-hover:text-lime-300 transition-colors">Python 3</h2> + <p class="text-sm text-neutral-500 mb-6 leading-relaxed"> + Full Python 3 environment with pip support. Includes enhanced indentation and real-time execution. + </p> + <div class="flex items-center text-xs font-mono text-lime-300 uppercase tracking-widest"> + Launch <i class="fas fa-arrow-right ml-2 group-hover:translate-x-1 transition-transform"></i> </div> </a> - <!-- Delete History --> - <button onclick="confirmClearHistory()" class="w-full p-3 hover:bg-red-500/10 rounded-xl transition-colors cursor-pointer flex items-center gap-3 group text-left"> - <div class="p-2 bg-red-500/10 rounded-lg text-red-400 group-hover:bg-red-500/20"><i data-lucide="trash-2" class="w-4 h-4"></i></div> - <div> - <h3 class="text-red-400 text-sm font-medium">Clear Activity</h3> - <p class="text-xs text-gemini-textSecondary">Remove local session data</p> - </div> - </button> - - <p class="text-center text-xs text-gemini-textSecondary pt-4 font-mono">Ada AI v1.4.0 • <a href="https://github.com/notamitgamer" class="hover:text-white underline">@notamitgamer</a></p> - </div> - </div> - </div> - - <!-- Sidebar (Collapsible Drawer on ALL screens) --> - <aside id="sidebar" class="bg-gemini-surface w-[280px] flex-shrink-0 flex flex-col border-r border-gemini-surfaceHover fixed inset-y-0 left-0 transform -translate-x-full z-[60] drawer shadow-2xl"> - <!-- Sidebar Header --> - <div class="h-16 flex items-center justify-between px-4"> - <button onclick="toggleSidebar()" class="p-2 text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover rounded-full transition-colors"> - <i data-lucide="menu" class="w-5 h-5"></i> - </button> - <span class="text-gemini-textSecondary text-xs font-medium uppercase tracking-wider">History</span> - - <div class="relative w-full max-w-[140px] ml-4"> - <input type="text" id="history-search" placeholder="Search..." oninput="filterHistory(this.value)" class="w-full bg-[#131314] text-xs text-white border border-gemini-surfaceHover rounded-md px-2 py-1 focus:outline-none focus:border-gemini-blue"> - <i data-lucide="search" class="absolute right-2 top-1.5 w-3 h-3 text-gemini-textSecondary"></i> </div> - </div> + </main> - <!-- New Chat Button --> - <div class="px-3 mb-2"> - <button onclick="startNewChat()" class="w-full bg-gemini-surfaceHover hover:bg-[#333537] text-gemini-textSecondary hover:text-white py-3 px-4 rounded-full flex items-center gap-3 transition-colors text-sm font-medium"> - <i data-lucide="plus" class="w-5 h-5"></i> - <span>New chat</span> - </button> - </div> + <a href="#features" class="absolute bottom-10 animate-bounce text-neutral-600 hover:text-white transition-colors"> + <i class="fas fa-chevron-down text-xl"></i> + </a> + </div> - <!-- Chat History List --> - <div id="chat-history-list" class="flex-1 overflow-y-auto px-2 py-2 space-y-1"> - <div class="flex items-center justify-center h-20 opacity-50"> - <div class="w-5 h-5 border-2 border-gemini-textSecondary border-t-transparent rounded-full animate-spin"></div> + <!-- Features Section --> + <section id="features" class="py-32 px-6 border-t border-white/5 bg-black/20 z-10"> + <div class="max-w-6xl mx-auto"> + <div class="text-center mb-20" data-aos="fade-up"> + <h2 class="text-3xl sm:text-4xl font-heading font-bold text-white mb-4">Features & <span class="text-lime-300">Capabilities</span></h2> + <p class="text-neutral-400 max-w-xl mx-auto">Upgraded with developer-focused tools for a complete coding experience.</p> </div> - </div> - <!-- User Profile (Bottom) --> - <div class="p-4 border-t border-gemini-surfaceHover space-y-1"> - <button onclick="toggleSettingsModal()" class="w-full flex items-center gap-3 p-2 hover:bg-gemini-surfaceHover rounded-lg transition-colors text-left text-gemini-textSecondary hover:text-white"> - <i data-lucide="settings" class="w-4 h-4"></i> - <span class="text-sm font-medium">Settings</span> - </button> - - <button onclick="toggleProfileModal()" class="w-full flex items-center gap-3 p-2 hover:bg-gemini-surfaceHover rounded-lg transition-colors text-left group mt-1"> - <div class="w-7 h-7 rounded-full bg-gradient-to-tr from-blue-500 to-purple-500 flex items-center justify-center text-[10px] font-bold text-white overflow-hidden"> - <img id="user-avatar" class="w-full h-full object-cover hidden" src="" alt="User"> - <span id="user-initial">U</span> - </div> - <div class="flex-1 min-w-0"> - <p id="user-email" class="text-xs text-gemini-textSecondary truncate">Not signed in</p> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> + <!-- Feature: Pro Editor --> + <div class="feature-card" data-aos="fade-up" data-aos-delay="100"> + <i class="fas fa-code text-lime-300 mb-4 text-xl"></i> + <h3 class="text-lg font-bold text-white mb-2">Pro Code Editor</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Powered by CodeMirror with Dracula theme, syntax highlighting, bracket matching, and line numbers.</p> </div> - </button> - </div> - </aside> - <!-- Overlay for Sidebar --> - <div id="sidebar-overlay" onclick="toggleSidebar()" class="fixed inset-0 bg-black/50 z-[55] hidden backdrop-blur-sm transition-opacity"></div> + <!-- Feature: AI Debug --> + <div class="feature-card border-lime-300/30" data-aos="fade-up" data-aos-delay="200"> + <div class="flex justify-between items-start"> + <i class="fas fa-robot text-lime-300 mb-4 text-xl"></i> + <span class="text-[10px] bg-lime-300 text-black px-2 py-0.5 rounded font-bold uppercase">New</span> + </div> + <h3 class="text-lg font-bold text-white mb-2">AI Auto-Debug</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Detects runtime errors and offers one-click code fixes powered by Gemini 2.5 Flash.</p> + </div> - <!-- Main Content Area --> - <main class="flex-1 flex flex-col relative w-full h-full min-w-0 bg-gemini-bg"> - - <!-- Top Bar (Fixed) --> - <header class="h-16 flex items-center justify-between px-4 md:px-6 sticky top-0 z-30 bg-gemini-bg/80 backdrop-blur-md border-b border-transparent transition-colors"> - <div class="flex items-center gap-2"> - <button onclick="toggleSidebar()" class="p-2 -ml-2 text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover rounded-full transition-colors" title="Toggle History"> - <i data-lucide="menu" class="w-6 h-6"></i> - </button> - <span class="text-lg font-medium text-white tracking-tight flex items-center gap-2"> - <span class="flex items-center gap-2"> - Ada <span class="text-gemini-blue text-xs font-normal border border-gemini-surfaceHover px-2 py-0.5 rounded-full bg-gemini-surface">Beta</span> - </span> - </span> - </div> - - <!-- Code Viewer Toggle & Login Trigger for Shared View --> - <div class="flex items-center gap-2"> - <button id="shared-login-btn" onclick="signInWithGoogle()" class="hidden px-4 py-2 bg-white text-black rounded-full text-sm font-medium hover:bg-gray-200 transition-colors"> - Sign In to Save - </button> - - <button onclick="toggleArtifactPanel()" class="p-2 text-gemini-textSecondary hover:text-gemini-blue relative rounded-full hover:bg-gemini-surfaceHover transition-colors" title="Toggle Code Viewer"> - <i data-lucide="panel-right" class="w-6 h-6"></i> - <span id="artifact-indicator" class="absolute top-2 right-2 w-2.5 h-2.5 bg-gemini-blue border-2 border-gemini-bg rounded-full hidden shadow-glow"></span> - </button> - </div> - </header> + <!-- Feature: Persistence --> + <div class="feature-card" data-aos="fade-up" data-aos-delay="300"> + <i class="fas fa-save text-lime-300 mb-4 text-xl"></i> + <h3 class="text-lg font-bold text-white mb-2">Auto-Save & Share</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Never lose work. Code is saved locally automatically and can be stored in the cloud via share links.</p> + </div> - <!-- Chat Container --> - <div id="chat-container" class="flex-1 overflow-y-auto px-4 md:px-0 pb-32 pt-4 scroll-smooth"> - <div class="max-w-3xl mx-auto flex flex-col gap-6"> - <!-- Welcome Message --> - <div id="welcome-message" class="flex flex-col items-start justify-center min-h-[50vh] space-y-8 animate-slide-up px-2"> - <div class="space-y-2 w-full"> - <div class="w-12 h-12 mb-4 animate-spin-slow-entry"> - <svg class="w-full h-full drop-shadow-[0_0_15px_rgba(168,199,250,0.5)]"><use href="#icon-ada"></use></svg> - </div> - <h1 class="text-4xl md:text-5xl font-medium text-transparent bg-clip-text bg-gradient-to-r from-[#4285F4] via-[#9B72CB] to-[#D96570] pb-2"> - Hello, <span id="welcome-name" class="text-white truncate block md:inline max-w-[200px] md:max-w-none">Student</span> - </h1> - <h2 class="text-3xl md:text-5xl font-medium text-gemini-surfaceHover/50">How can I help you code today?</h2> - </div> + <!-- Feature: Mobile --> + <div class="feature-card" data-aos="fade-up" data-aos-delay="400"> + <i class="fas fa-mobile-alt text-lime-300 mb-4 text-xl"></i> + <h3 class="text-lg font-bold text-white mb-2">Mobile Optimized</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Includes a custom helper bar for quick access to symbols like <code>{ } [ ] ;</code> on touch devices.</p> + </div> - <!-- Suggestion Chips (Hidden on Mobile) --> - <div class="hidden md:flex flex-wrap gap-3 w-full" id="suggestion-chips"> - <button onclick="setPrompt('Debug this Python script')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-gemini-blue group-hover:translate-x-1 transition-transform"><i data-lucide="bug" class="w-4 h-4 inline mr-1"></i> Debug</span> - Find errors in code - </button> - <button onclick="setPrompt('Explain this concept')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-gemini-purple group-hover:translate-x-1 transition-transform"><i data-lucide="book-open" class="w-4 h-4 inline mr-1"></i> Explain</span> - Understand algorithms - </button> - <button onclick="setPrompt('Refactor this function')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-green-400 group-hover:translate-x-1 transition-transform"><i data-lucide="wand-2" class="w-4 h-4 inline mr-1"></i> Refactor</span> - Optimize performance - </button> - </div> + <!-- Feature: Backend --> + <div class="feature-card" data-aos="fade-up" data-aos-delay="500"> + <i class="fas fa-server text-lime-300 mb-4 text-xl"></i> + <h3 class="text-lg font-bold text-white mb-2">Real Backend</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Code runs on a live Linux instance via WebSockets for authentic I/O streaming performance.</p> </div> - </div> - </div> - <!-- Input Area (Fixed Bottom) --> - <div class="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-gemini-bg via-gemini-bg to-transparent z-20" id="input-area"> - <div class="max-w-3xl mx-auto"> - <form id="chat-form" onsubmit="handleFormSubmit(event)" class="bg-gemini-surface rounded-[28px] flex items-end p-2 border border-gemini-surfaceHover focus-within:bg-gemini-surfaceHover focus-within:border-gemini-textSecondary/20 transition-all shadow-xl"> - <textarea - id="user-input" - class="w-full bg-transparent text-white placeholder-gemini-textSecondary py-3.5 px-4 max-h-48 min-h-[52px] resize-none focus:outline-none text-base no-scrollbar" - placeholder="Enter a prompt here" - rows="1" - oninput="autoResize(this)" - onkeydown="handleEnter(event)" - enterkeyhint="send" - ></textarea> - - <button type="submit" id="send-btn" class="p-3 text-gemini-textSecondary hover:text-white disabled:opacity-50 disabled:cursor-not-allowed transition-colors rounded-full"> - <i data-lucide="send-horizontal" class="w-6 h-6"></i> - </button> - </form> - <div class="text-center mt-3 text-xs text-gemini-textSecondary/60"> - Ada may display inaccurate info, including about people, so double-check its responses. + <!-- Feature: Export --> + <div class="feature-card" data-aos="fade-up" data-aos-delay="600"> + <i class="fas fa-download text-lime-300 mb-4 text-xl"></i> + <h3 class="text-lg font-bold text-white mb-2">One-Click Export</h3> + <p class="text-sm text-neutral-500 leading-relaxed">Download your source code directly as a <code>.py</code>, <code>.c</code>, or <code>.cpp</code> file.</p> </div> </div> </div> - </main> + </section> - <!-- Right Artifact Panel (Drawer on ALL screens) --> - <aside id="artifact-panel" class="fixed inset-y-0 right-0 z-[70] w-full md:w-[600px] bg-[#1e1e1e] border-l border-[#333] transform translate-x-full drawer shadow-2xl flex flex-col"> - <!-- Panel Header --> - <div class="h-14 flex-shrink-0 flex items-center justify-between px-4 bg-[#252526] border-b border-[#333]"> - <div class="flex items-center gap-3"> - <span class="text-xs uppercase tracking-wide text-[#969696] font-medium">Workspace</span> - <span id="lang-display" class="text-xs text-[#cccccc] bg-[#3c3c3c] px-2 py-0.5 rounded">PLAINTEXT</span> + <!-- Footer --> + <footer class="py-12 border-t border-white/5 z-10 bg-black/40"> + <div class="max-w-6xl mx-auto px-6 text-center"> + + <div class="mb-8"> + <a href="./docs.html" class="inline-flex items-center gap-2 text-sm font-mono text-neutral-500 hover:text-lime-300 transition-colors uppercase tracking-widest border border-white/10 px-4 py-2 rounded-full bg-white/5 hover:bg-white/10"> + <i class="fas fa-book"></i> Read Documentation + </a> </div> - <div class="flex gap-2"> - <button onclick="copyArtifact()" class="p-2 text-[#cccccc] hover:text-white hover:bg-[#3c3c3c] rounded transition-colors" title="Copy Code"> - <i data-lucide="copy" class="w-4 h-4"></i> - </button> - <button onclick="toggleArtifactPanel()" class="p-2 text-[#cccccc] hover:text-white hover:bg-[#3c3c3c] rounded transition-colors" title="Close"> - <i data-lucide="x" class="w-5 h-5"></i> - </button> + + <h3 class="text-xl font-heading font-bold text-white mb-8">Connect with Me</h3> + + <div class="flex flex-wrap justify-center gap-4 mb-12"> + <a href="https://github.com/notamitgamer" target="_blank" class="social-link w-12 h-12 rounded-full flex items-center justify-center text-lg"> + <i class="fab fa-github"></i> + </a> + <a href="https://linkedin.com/in/notamitgamer" target="_blank" class="social-link w-12 h-12 rounded-full flex items-center justify-center text-lg"> + <i class="fab fa-linkedin-in"></i> + </a> + <a href="https://twitter.com/notamitgamer" target="_blank" class="social-link w-12 h-12 rounded-full flex items-center justify-center text-lg"> + <i class="fab fa-twitter"></i> + </a> + <a href="https://instagram.com/notamitgamer" target="_blank" class="social-link w-12 h-12 rounded-full flex items-center justify-center text-lg"> + <i class="fab fa-instagram"></i> + </a> </div> - </div> - <!-- Editor Content --> - <div class="flex-1 overflow-hidden relative bg-[#1e1e1e]"> - <textarea id="artifact-editor" class="w-full h-full"></textarea> + <div class="text-neutral-600 text-sm font-mono space-y-2"> + <p>&copy; 2025 Amit Dutta. All rights reserved.</p> + <p><a href="https://amit.is-a.dev" class="hover:text-lime-300 transition-colors">amit.is-a.dev</a></p> + </div> </div> - </aside> + </footer> + <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> <script> - // --- CONFIGURATION --- - const API_BASE_URL = "https://ada-web.onrender.com/api"; - - const firebaseConfig = { - apiKey: "AIzaSyAhyoNYUSXWIxdBiTxwSDcU7HkhhLEVlOc", - authDomain: "ada-ai-aranag.firebaseapp.com", - projectId: "ada-ai-aranag", - storageBucket: "ada-ai-aranag.firebasestorage.app", - messagingSenderId: "865895114061", - appId: "1:865895114061:web:5fd4493b0e388727e6c304" - }; - - // --- STATE & INIT --- - let auth, db; - let state = { - messages: [], - isTyping: false, - currentChatId: null, - user: null, - isSharedView: false - }; - let editor = null; - let settings = { - allowSharing: localStorage.getItem('ada_allow_sharing') === 'true', - fontSize: parseInt(localStorage.getItem('ada_font_size')) || 14 - }; - - function initApp() { - lucide.createIcons(); - - // Set initial settings - applyFontSize(settings.fontSize); - - const shareToggle = document.getElementById('share-toggle-checkbox'); - if(shareToggle) shareToggle.checked = settings.allowSharing; - - // Check for Shared URL param - const urlParams = new URLSearchParams(window.location.search); - const sharedChatId = urlParams.get('chat'); - if (sharedChatId) { - state.isSharedView = true; - state.currentChatId = sharedChatId; - enterSharedMode(sharedChatId); - } - - // Initialize CodeMirror (Standard setup) - editor = CodeMirror.fromTextArea(document.getElementById("artifact-editor"), { - lineNumbers: true, - mode: "javascript", - theme: "dracula", - readOnly: true, // Read-only as it's an output viewer primarily - lineWrapping: true - }); - - // Initialize Firebase - try { - firebase.initializeApp(firebaseConfig); - auth = firebase.auth(); - db = firebase.firestore(); - if (!state.isSharedView) checkAuth(); - else checkAuthShared(); - } catch (e) { - console.error("Init Failed:", e); - document.getElementById('loading-overlay').classList.add('opacity-0', 'pointer-events-none'); - } - - // Mobile Height Fix - const setVh = () => { - let vh = window.innerHeight * 0.01; - document.documentElement.style.setProperty('--vh', `${vh}px`); - }; - window.addEventListener('resize', setVh); - setVh(); - - // Context Menu Listener - document.addEventListener('click', (e) => { - const menu = document.querySelector('.context-menu'); - if (menu) menu.remove(); - }); - } - - function autoResize(textarea) { - textarea.style.height = 'auto'; - textarea.style.height = Math.min(textarea.scrollHeight, 200) + 'px'; - } - - // --- SETTINGS --- - function changeFontSize(delta) { - settings.fontSize = Math.max(10, Math.min(24, settings.fontSize + delta)); - localStorage.setItem('ada_font_size', settings.fontSize); - applyFontSize(settings.fontSize); - } - - function applyFontSize(size) { - document.getElementById('font-size-display').innerText = size; - if(editor) { - editor.getWrapperElement().style.fontSize = `${size}px`; - editor.refresh(); - } - } - - // --- SHARED MODE LOGIC --- - async function enterSharedMode(chatId) { - document.getElementById('sidebar').classList.add('hidden'); - const inputArea = document.getElementById('input-area'); - const sidebarToggle = document.querySelector('header button[title="Toggle History"]'); - - inputArea.classList.add('hidden'); - if(sidebarToggle) sidebarToggle.style.display = 'none'; - } - - function checkAuthShared() { - auth.onAuthStateChanged(user => { - const loadingOverlay = document.getElementById('loading-overlay'); - loadingOverlay.classList.add('opacity-0', 'pointer-events-none'); - - if (user) { - state.user = user; - document.getElementById('sidebar').classList.remove('hidden'); - document.getElementById('input-area').classList.remove('hidden'); - const sidebarToggle = document.querySelector('header button[title="Toggle History"]'); - if(sidebarToggle) sidebarToggle.style.display = 'block'; - document.getElementById('shared-login-btn').classList.add('hidden'); - - fetchChats(); - loadChat(state.currentChatId); - } else { - state.user = null; - document.getElementById('shared-login-btn').classList.remove('hidden'); - loadChatReadOnly(state.currentChatId); - } - }); - } - - async function loadChatReadOnly(chatId) { - const container = document.querySelector('#chat-container > div'); - container.innerHTML = ` - <div class="flex flex-col items-center justify-center min-h-[50vh] text-center p-6"> - <div class="p-4 bg-gemini-surface rounded-2xl border border-gemini-surfaceHover mb-4"> - <i data-lucide="lock" class="w-8 h-8 text-gemini-textSecondary mx-auto mb-2"></i> - <p class="text-white font-medium">Shared Chat</p> - </div> - <p class="text-gemini-textSecondary max-w-md">To view and continue this conversation, please sign in. The chat will be saved to your history.</p> - </div> - `; - lucide.createIcons(); - } - - // --- UI TOGGLES & HELPERS --- - function showToast(message, type = 'info') { - const toast = document.getElementById('toast'); - const icon = toast.querySelector('i'); - document.getElementById('toast-message').innerText = message; - - if (type === 'error') { - icon.setAttribute('data-lucide', 'alert-circle'); - icon.className = 'w-4 h-4 text-red-400'; - } else if (type === 'success') { - icon.setAttribute('data-lucide', 'check-circle'); - icon.className = 'w-4 h-4 text-green-400'; - } else { - icon.setAttribute('data-lucide', 'info'); - icon.className = 'w-4 h-4 text-gemini-blue'; - } - lucide.createIcons(); - - toast.classList.remove('opacity-0', 'pointer-events-none', 'translate-y-20'); - setTimeout(() => { - toast.classList.add('opacity-0', 'pointer-events-none', 'translate-y-20'); - }, 3000); - } - - function toggleShareSetting(checkbox) { - settings.allowSharing = checkbox.checked; - localStorage.setItem('ada_allow_sharing', settings.allowSharing); - } - - function toggleSidebar() { - const sb = document.getElementById('sidebar'); - const overlay = document.getElementById('sidebar-overlay'); - const isClosed = sb.classList.contains('-translate-x-full'); - - if (isClosed) { - sb.classList.remove('-translate-x-full'); - overlay.classList.remove('hidden'); - } else { - sb.classList.add('-translate-x-full'); - overlay.classList.add('hidden'); - } - } - - function toggleArtifactPanel() { - const panel = document.getElementById('artifact-panel'); - const isClosed = panel.classList.contains('translate-x-full'); - - if (isClosed) { - panel.classList.remove('translate-x-full'); - document.getElementById('artifact-indicator').classList.add('hidden'); - setTimeout(() => editor.refresh(), 300); - } else { - panel.classList.add('translate-x-full'); - } - } - - function toggleProfileModal() { - const modal = document.getElementById('profile-modal'); - const content = document.getElementById('profile-modal-content'); - - if (modal.classList.contains('hidden')) { - modal.classList.remove('hidden', 'pointer-events-none'); - requestAnimationFrame(() => { - modal.classList.remove('opacity-0'); - content.classList.remove('scale-95'); - content.classList.add('scale-100'); - }); - - if (state.user) { - document.getElementById('profile-name').innerText = state.user.displayName || 'User'; - document.getElementById('profile-email').innerText = state.user.email || ''; - const initial = document.getElementById('profile-initial'); - const avatar = document.getElementById('profile-avatar'); - - if (state.user.photoURL) { - avatar.src = state.user.photoURL; - avatar.classList.remove('hidden'); - initial.classList.add('hidden'); - } else { - initial.innerText = (state.user.displayName || 'U')[0]; - avatar.classList.add('hidden'); - initial.classList.remove('hidden'); - } - } - } else { - modal.classList.add('opacity-0'); - content.classList.remove('scale-100'); - content.classList.add('scale-95'); - setTimeout(() => modal.classList.add('hidden', 'pointer-events-none'), 300); - } - } - - function toggleSettingsModal() { - const modal = document.getElementById('settings-modal'); - const content = document.getElementById('settings-modal-content'); - - if (modal.classList.contains('hidden')) { - modal.classList.remove('hidden', 'pointer-events-none'); - requestAnimationFrame(() => { - modal.classList.remove('opacity-0'); - content.classList.remove('scale-95'); - content.classList.add('scale-100'); - }); - } else { - modal.classList.add('opacity-0'); - content.classList.remove('scale-100'); - content.classList.add('scale-95'); - setTimeout(() => modal.classList.add('hidden', 'pointer-events-none'), 300); - } - } - - // --- FEATURES IMPLEMENTATION --- - - // 1. History Search - function filterHistory(query) { - const list = document.getElementById('chat-history-list'); - const items = list.querySelectorAll('div[onclick]'); - query = query.toLowerCase(); - - items.forEach(item => { - const text = item.querySelector('span').innerText.toLowerCase(); - if (text.includes(query)) { - item.style.display = 'flex'; - } else { - item.style.display = 'none'; - } + document.addEventListener('DOMContentLoaded', () => { + AOS.init({ + duration: 800, + once: true, + offset: 50 }); - } - - // --- CONFIRM MODALS --- - let confirmCallback = null; - - function showConfirmModal(title, message, callback, matchText = null) { - const modal = document.getElementById('confirm-modal'); - const content = document.getElementById('confirm-modal-content'); - - document.getElementById('confirm-title').innerText = title; - document.getElementById('confirm-message').innerText = message; - - const inputContainer = document.getElementById('confirm-input-container'); - const input = document.getElementById('confirm-input'); - const btn = document.getElementById('confirm-action-btn'); - - if (matchText) { - inputContainer.classList.remove('hidden'); - document.getElementById('confirm-match-text').innerText = matchText; - input.value = ''; - input.oninput = () => { - if (input.value === matchText) { - btn.disabled = false; - btn.classList.remove('opacity-50', 'cursor-not-allowed'); - } else { - btn.disabled = true; - btn.classList.add('opacity-50', 'cursor-not-allowed'); - } - }; - btn.disabled = true; - btn.classList.add('opacity-50', 'cursor-not-allowed'); - } else { - inputContainer.classList.add('hidden'); - btn.disabled = false; - btn.classList.remove('opacity-50', 'cursor-not-allowed'); - } - - confirmCallback = callback; - - modal.classList.remove('hidden'); - requestAnimationFrame(() => { - modal.classList.remove('opacity-0'); - content.classList.remove('scale-95'); - content.classList.add('scale-100'); - }); - - btn.onclick = () => { - closeConfirmModal(); - if (confirmCallback) confirmCallback(); - }; - } - - function closeConfirmModal() { - const modal = document.getElementById('confirm-modal'); - const content = document.getElementById('confirm-modal-content'); - modal.classList.add('opacity-0'); - content.classList.remove('scale-100'); - content.classList.add('scale-95'); - setTimeout(() => modal.classList.add('hidden'), 300); - } - function confirmSignOut() { - toggleProfileModal(); - showConfirmModal('Sign Out', 'Are you sure you want to sign out?', signOutUser); - } - - function confirmClearHistory() { - toggleSettingsModal(); - if (!state.user || !state.user.email) return; - showConfirmModal( - 'Clear Activity', - 'This will permanently delete all your chat history. Type your email to confirm.', - clearHistory, - state.user.email - ); - } - - async function clearHistory() { - if (!state.user) return; - const loading = document.getElementById('loading-overlay'); - loading.classList.remove('opacity-0', 'pointer-events-none'); - - try { - // FIXED: Use correct path users/{uid}/chats - const chatsRef = db.collection('users').doc(state.user.uid).collection('chats'); - const snapshot = await chatsRef.get(); - - const batch = db.batch(); - snapshot.docs.forEach((doc) => { - batch.delete(doc.ref); - }); - await batch.commit(); - - location.reload(); - } catch (error) { - console.error("Error clearing history:", error); - loading.classList.add('opacity-0', 'pointer-events-none'); - showToast("Failed to clear history.", "error"); - } - } - - function confirmDeleteChat(chatId) { - showConfirmModal('Delete Chat', 'This action cannot be undone.', () => deleteChat(chatId)); - } - - async function deleteChat(chatId) { - if (!state.user) return; - try { - // FIXED: Use correct path users/{uid}/chats/{chatId} - await db.collection('users').doc(state.user.uid).collection('chats').doc(chatId).delete(); - - if (state.currentChatId === chatId) { - location.reload(); - } else { - fetchChats(); - showToast("Chat deleted.", "success"); + // Card Hover Effect (Mouse tracking) + const cards = document.querySelectorAll('.compiler-card'); + document.getElementById('compiler-grid').onmousemove = e => { + for(const card of cards) { + const rect = card.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + card.style.setProperty('--mouse-x', `${x}px`); + card.style.setProperty('--mouse-y', `${y}px`); } - } catch (e) { - console.error("Delete Error:", e); - showToast("Failed to delete chat.", "error"); - } - } - - // --- CONTEXT MENU & EXPORT --- - function showChatContextMenu(e, chatId, chatTitle) { - e.preventDefault(); - e.stopPropagation(); - - const existing = document.querySelector('.context-menu'); - if (existing) existing.remove(); - - const menu = document.createElement('div'); - menu.className = 'context-menu'; - - // Share Option - if (settings.allowSharing) { - const shareBtn = document.createElement('div'); - shareBtn.className = 'context-menu-item'; - shareBtn.innerHTML = `<i data-lucide="link" class="w-4 h-4"></i> Share Chat`; - shareBtn.onclick = async () => { - const url = `${window.location.origin}?chat=${chatId}`; - if (navigator.share) { - try { - await navigator.share({ title: 'Ada Chat', url: url }); - } catch (err) { /* Share cancelled */ } - } else { - navigator.clipboard.writeText(url).then(() => showToast('Link copied!', 'success')); - } - menu.remove(); - }; - menu.appendChild(shareBtn); - } - - // Export Options (Expanded) - const jsonBtn = document.createElement('div'); - jsonBtn.className = 'context-menu-item'; - jsonBtn.innerHTML = `<i data-lucide="file-json" class="w-4 h-4"></i> Export JSON`; - jsonBtn.onclick = () => { - downloadChat(chatId, chatTitle, 'json'); - menu.remove(); - }; - menu.appendChild(jsonBtn); - - const mdBtn = document.createElement('div'); - mdBtn.className = 'context-menu-item'; - mdBtn.innerHTML = `<i data-lucide="file-text" class="w-4 h-4"></i> Export Markdown`; - mdBtn.onclick = () => { - downloadChat(chatId, chatTitle, 'md'); - menu.remove(); }; - menu.appendChild(mdBtn); - - // Delete Option - const delBtn = document.createElement('div'); - delBtn.className = 'context-menu-item danger'; - delBtn.innerHTML = `<i data-lucide="trash-2" class="w-4 h-4"></i> Delete Chat`; - delBtn.onclick = () => { - confirmDeleteChat(chatId); - menu.remove(); - }; - menu.appendChild(delBtn); - - document.body.appendChild(menu); - - // Position - const rect = e.target.getBoundingClientRect(); - const menuWidth = 180; - const menuHeight = 200; - - let left = rect.left; - let top = rect.bottom + 5; - - if (left + menuWidth > window.innerWidth) left = window.innerWidth - menuWidth - 16; - if (left < 16) left = 16; - if (top + menuHeight > window.innerHeight) top = rect.top - menuHeight - 5; - - menu.style.top = `${top}px`; - menu.style.left = `${left}px`; - - lucide.createIcons(); - } - - async function downloadChat(chatId, title, format) { - try { - const token = await state.user.getIdToken(); - const res = await fetch(`${API_BASE_URL}/chats/${chatId}`, { headers: { 'Authorization': `Bearer ${token}` } }); - const data = await res.json(); - - let content, type, ext; - if (format === 'json') { - content = JSON.stringify(data, null, 2); - type = 'application/json'; - ext = 'json'; - } else { - // Markdown conversion - content = `# ${title}\n\n`; - data.messages.forEach(msg => { - content += `### ${msg.role === 'user' ? 'User' : 'Ada AI'}\n${msg.content}\n\n`; - }); - type = 'text/markdown'; - ext = 'md'; - } - - const blob = new Blob([content], { type: type }); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `ada_chat_${title.replace(/\s+/g, '_')}.${ext}`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - showToast("Chat exported.", "success"); - } catch(e) { - console.error(e); - showToast("Export failed.", "error"); - } - } - - // --- AUTH & FIREBASE --- - function checkAuth() { - auth.onAuthStateChanged(user => { - const loadingOverlay = document.getElementById('loading-overlay'); - const authModal = document.getElementById('auth-modal'); - - if (user) { - state.user = user; - localStorage.setItem('ada_user_cached', 'true'); - - loadingOverlay.classList.add('opacity-0', 'pointer-events-none'); - authModal.classList.add('hidden'); - document.getElementById('user-email').innerText = user.email || ''; - document.getElementById('user-initial').innerText = (user.displayName || 'U')[0]; - - const welcomeName = document.getElementById('welcome-name'); - if (welcomeName) { - const name = user.email || user.displayName || 'Student'; - welcomeName.innerText = name; - welcomeName.title = name; - } - - if (user.photoURL) { - const img = document.getElementById('user-avatar'); - img.src = user.photoURL; - img.classList.remove('hidden'); - document.getElementById('user-initial').classList.add('hidden'); - } - - if(!state.currentChatId) state.currentChatId = 'session_' + Date.now(); - fetchChats(); - } else { - state.user = null; - localStorage.removeItem('ada_user_cached'); - loadingOverlay.classList.add('opacity-0', 'pointer-events-none'); - authModal.classList.remove('hidden', 'opacity-0', 'pointer-events-none'); - } - }); - } - - function signInWithGoogle() { - const provider = new firebase.auth.GoogleAuthProvider(); - auth.signInWithPopup(provider).catch(e => { - console.error(e); - showToast("Sign in failed.", "error"); - }); - } - - function signOutUser() { - auth.signOut().then(() => { - localStorage.removeItem('ada_user_cached'); - location.reload(); - }); - } - - async function fetchChats() { - if (!state.user) return; - try { - // Skeleton loading for sidebar could go here - - const token = await state.user.getIdToken(); - const res = await fetch(`${API_BASE_URL}/chats`, { headers: { 'Authorization': `Bearer ${token}` } }); - const data = await res.json(); - - const list = document.getElementById('chat-history-list'); - list.innerHTML = ''; - - if (data.chats && data.chats.length > 0) { - data.chats.forEach(chat => { - const div = document.createElement('div'); - const isActive = chat.id === state.currentChatId; - div.className = `group relative p-2.5 rounded-full cursor-pointer text-sm flex items-center gap-3 transition-colors truncate ${isActive ? 'bg-[#004A77] text-white font-medium' : 'text-gemini-textSecondary hover:bg-gemini-surfaceHover hover:text-white'}`; - div.onclick = () => loadChat(chat.id); - - let pressTimer; - div.ontouchstart = (e) => { - pressTimer = setTimeout(() => showChatContextMenu(e, chat.id, chat.title), 500); - }; - div.ontouchend = () => clearTimeout(pressTimer); - div.oncontextmenu = (e) => showChatContextMenu(e, chat.id, chat.title); - - div.innerHTML = ` - <i data-lucide="message-square" class="w-4 h-4 flex-shrink-0"></i> - <span class="truncate flex-1">${chat.title}</span> - <button class="opacity-0 group-hover:opacity-100 p-1 hover:bg-white/10 rounded-full transition-opacity" onclick="showChatContextMenu(event, '${chat.id}', '${chat.title}')"> - <i data-lucide="more-vertical" class="w-3 h-3"></i> - </button> - `; - list.appendChild(div); - }); + // Typewriter logic + const typeTextElement = document.getElementById('type-text'); + const createTextElement = document.getElementById('create-text'); + const textToType = "Code. Compile."; + let i = 0; + const speed = 75; // ms per char + + function typeWriter() { + if (i < textToType.length) { + typeTextElement.textContent += textToType.charAt(i); + i++; + setTimeout(typeWriter, speed); } else { - list.innerHTML = `<div class="p-4 text-center text-xs text-gemini-textSecondary">No recent chats</div>`; - } - lucide.createIcons(); - } catch (e) { console.error(e); } - } - - async function loadChat(chatId) { - if (state.isTyping) return; - state.currentChatId = chatId; - - // Skeleton Loading - const container = document.querySelector('#chat-container > div'); - container.innerHTML = ` - <div class="flex flex-col space-y-4 p-4 animate-pulse"> - <div class="flex justify-end"><div class="h-10 w-2/3 bg-gemini-surfaceHover rounded-xl"></div></div> - <div class="flex justify-start"><div class="h-20 w-3/4 bg-gemini-surfaceHover rounded-xl"></div></div> - <div class="flex justify-end"><div class="h-8 w-1/2 bg-gemini-surfaceHover rounded-xl"></div></div> - </div>`; - - try { - const token = await state.user.getIdToken(); - const res = await fetch(`${API_BASE_URL}/chats/${chatId}`, { headers: { 'Authorization': `Bearer ${token}` } }); - const data = await res.json(); - - state.messages = []; - container.innerHTML = ''; - - if (data.messages && data.messages.length > 0) { - data.messages.forEach(msg => { - const role = msg.role === 'model' ? 'ai' : 'user'; - state.messages.push({ role, content: msg.content }); - renderMessage(role, msg.content); - }); - } else { - container.innerHTML = `<div class="text-center p-8 text-gemini-textSecondary">Start conversation...</div>`; - } - - if(!state.isSharedView) fetchChats(); - } catch (e) { - console.error(e); - container.innerHTML = `<div class="text-center text-red-400 p-4">Failed to load chat.</div>`; - } - } - - function setPrompt(text) { - const input = document.getElementById('user-input'); - if(input) { - input.value = text; - input.focus(); - autoResize(input); - } - } - - function scrollToBottom() { - const container = document.getElementById('chat-container'); - container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' }); - } - - function renderMessage(role, content) { - const container = document.querySelector('#chat-container > div'); - const welcome = document.getElementById('welcome-message'); - if (welcome) welcome.remove(); - - let wrapper = container.lastElementChild; - let bubble = null; - - if (role === 'ai' && wrapper && wrapper.dataset.role === 'ai' && state.isTyping) { - bubble = wrapper.querySelector('.prose'); - } else { - wrapper = document.createElement('div'); - wrapper.className = `flex gap-4 w-full animate-fade-in ${role === 'user' ? 'justify-end' : 'justify-start group'}`; - wrapper.dataset.role = role; - - if (role === 'user') { - wrapper.innerHTML = `<div class="msg-user text-sm md:text-base">${content}</div>`; - } else { - wrapper.innerHTML = ` - <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center mt-1"> - <svg class="w-6 h-6 animate-spin-slow-entry"><use href="#icon-ada"></use></svg> - </div> - <div class="flex-1 min-w-0 py-1"> - <div class="prose prose-invert max-w-none text-sm md:text-base"></div> - </div> - `; - bubble = wrapper.querySelector('.prose'); - } - container.appendChild(wrapper); - } - - if (role === 'ai') { - if(!bubble) bubble = wrapper.querySelector('.prose'); - - const customTagRegex = /<<<CODE_START>>>([\s\S]*?)<<<CODE_END>>>/g; - const markdownRegex = /```(\w*)([\s\S]*?)```/g; - - let processedContent = content; - let extractedCode = ""; - let lang = "PLAINTEXT"; - - const cardReplacement = (code, language) => { - extractedCode = code.trim(); - if(language) lang = language.toUpperCase(); - return `<div class="code-card group" onclick="toggleArtifactPanel()"> - <div class="px-4 py-3 bg-[#252526] border-b border-[#333] flex items-center justify-between"> - <div class="flex items-center gap-2"> - <i data-lucide="code-2" class="w-4 h-4 text-gemini-blue"></i> - <span class="text-xs font-mono text-[#cccccc]">Generated Code</span> - </div> - <span class="text-xs text-gemini-blue group-hover:underline">View Code &rarr;</span> - </div> - <div class="px-4 py-3 text-xs font-mono text-gray-400 bg-[#1e1e1e]"> - // Code extracted to workspace... - </div> - </div>`; - }; - - processedContent = processedContent.replace(customTagRegex, (m, c) => cardReplacement(c)); - processedContent = processedContent.replace(markdownRegex, (m, l, c) => cardReplacement(c, l)); - - try { - bubble.innerHTML = marked.parse(processedContent); - } catch (e) { - bubble.innerText = content; - } - - if (extractedCode) { - updateArtifactPanel(extractedCode, lang); - const indicator = document.getElementById('artifact-indicator'); - if(indicator) indicator.classList.remove('hidden'); + // Typing done, show "Create." with fade-in + createTextElement.classList.remove('hidden'); - if (window.innerWidth >= 1280) { - const panel = document.getElementById('artifact-panel'); - if (panel.classList.contains('translate-x-full')) { - toggleArtifactPanel(); - } - } - } - } - - scrollToBottom(); - lucide.createIcons(); - } - - function renderTypingIndicator() { - const container = document.querySelector('#chat-container > div'); - const wrapper = document.createElement('div'); - wrapper.id = 'typing-indicator'; - wrapper.className = 'flex gap-4 w-full justify-start animate-fade-in'; - wrapper.innerHTML = ` - <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center mt-1"> - <svg class="w-6 h-6 animate-pulse"><use href="#icon-ada"></use></svg> - </div> - <div class="py-3"> - <div class="flex gap-1"> - <div class="typing-dot"></div> - <div class="typing-dot"></div> - <div class="typing-dot"></div> - </div> - </div> - `; - container.appendChild(wrapper); - scrollToBottom(); - lucide.createIcons(); - } - - function removeTypingIndicator() { - const el = document.getElementById('typing-indicator'); - if (el) el.remove(); - } - - function updateArtifactPanel(code, lang) { - const langDisplay = document.getElementById('lang-display'); - if(lang) { - langDisplay.innerText = lang; - const modeMap = { - 'PYTHON': 'python', - 'JAVASCRIPT': 'javascript', - 'JS': 'javascript', - 'HTML': 'xml', - 'CSS': 'css' - }; - if(editor) editor.setOption("mode", modeMap[lang] || "javascript"); - } - - if(editor) { - editor.setValue(code); - setTimeout(() => editor.refresh(), 100); - } - } - - function copyArtifact() { - if(editor) { - const content = editor.getValue(); - navigator.clipboard.writeText(content); - showToast("Code copied to clipboard!", "success"); - } - } - - function handleEnter(e) { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - handleFormSubmit(e); - } - } - - async function handleFormSubmit(e) { - if (e) e.preventDefault(); - const input = document.getElementById('user-input'); - const message = input.value.trim(); - if (!message || state.isTyping || !state.user) return; - - // UI Updates - renderMessage('user', message); - input.value = ''; - autoResize(input); - state.isTyping = true; - renderTypingIndicator(); - - try { - const token = await state.user.getIdToken(); - const response = await fetch(`${API_BASE_URL}/chat`, { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, - body: JSON.stringify({ - message: message, - history: state.messages.map(m => ({ user: m.role === 'user' ? m.content : '', model: m.role === 'ai' ? m.content : '' })), - sessionId: state.currentChatId - }) - }); - - if (!response.ok) throw new Error("API Error"); - - removeTypingIndicator(); - const reader = response.body.getReader(); - const decoder = new TextDecoder(); - let fullText = ""; - renderMessage('ai', ''); - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - fullText += decoder.decode(value); - renderMessage('ai', fullText); + // Trigger subtext fade + document.querySelector('.sub-text-fade').style.animation = 'fadeInDown 2s ease-in-out forwards 0.5s'; } - - state.messages.push({ role: 'user', content: message }); - state.messages.push({ role: 'ai', content: fullText }); - setTimeout(fetchChats, 1500); - - } catch (error) { - removeTypingIndicator(); - renderMessage('ai', "I'm having trouble connecting right now."); - showToast("Error generating response", "error"); - } finally { - state.isTyping = false; } - } - - function startNewChat() { - state.messages = []; - state.currentChatId = 'session_' + Date.now(); - - const userName = state.user ? (state.user.email || state.user.displayName || 'Student') : 'Student'; - const container = document.querySelector('#chat-container > div'); - container.innerHTML = ` - <div id="welcome-message" class="flex flex-col items-start justify-center min-h-[50vh] space-y-8 animate-slide-up px-2"> - <div class="space-y-2 w-full"> - <div class="w-12 h-12 mb-4 animate-spin-slow-entry"> - <svg class="w-full h-full drop-shadow-[0_0_15px_rgba(168,199,250,0.5)]"><use href="#icon-ada"></use></svg> - </div> - <h1 class="text-4xl md:text-5xl font-medium text-transparent bg-clip-text bg-gradient-to-r from-[#4285F4] via-[#9B72CB] to-[#D96570] pb-2"> - Hello, <span id="welcome-name" class="text-white truncate block md:inline max-w-[200px] md:max-w-none">${userName}</span> - </h1> - <h2 class="text-3xl md:text-5xl font-medium text-gemini-surfaceHover/50">How can I help you code today?</h2> - </div> - <div class="hidden md:flex flex-wrap gap-3 w-full"> - <button onclick="setPrompt('Debug this Python script')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-gemini-blue group-hover:translate-x-1 transition-transform"><i data-lucide="bug" class="w-4 h-4 inline mr-1"></i> Debug</span> - </button> - <button onclick="setPrompt('Explain this concept')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-gemini-purple group-hover:translate-x-1 transition-transform"><i data-lucide="book-open" class="w-4 h-4 inline mr-1"></i> Explain</span> - </button> - <button onclick="setPrompt('Refactor this function')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover"> - <span class="block mb-1 text-green-400 group-hover:translate-x-1 transition-transform"><i data-lucide="wand-2" class="w-4 h-4 inline mr-1"></i> Refactor</span> - </button> - </div> - </div>`; - lucide.createIcons(); - fetchChats(); - } - - window.onload = initApp; - + // Start typing after a short delay + setTimeout(typeWriter, 500); + }); </script> </body> </html> \ No newline at end of file diff --git a/docs/logo.png b/docs/logo.png Binary files differ. diff --git a/docs/python.html b/docs/python.html @@ -0,0 +1,1027 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + <title>Amit Dutta // Python Compiler</title> + <link rel="icon" type="image/x-icon" href="https://compiler.aranag.site/logo.png"> + + <!-- Fonts & Icons --> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"> + + <!-- Tailwind CSS --> + <script src="https://cdn.tailwindcss.com"></script> + + <!-- CodeMirror 5 (Professional Editor) --> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/python/python.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/closebrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/matchbrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/selection/active-line.min.js"></script> + + <!-- Xterm.js --> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" /> + <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script> + <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script> + + <style> + :root { + --bg-main: #050505; + --accent: #bef264; /* Lime 300 */ + --text-muted: #737373; + --border-color: rgba(255, 255, 255, 0.1); + } + + body { + font-family: 'Inter', sans-serif; + background-color: var(--bg-main); + color: #f5f5f5; + height: 100vh; + height: 100dvh; + overflow: hidden; + display: flex; + flex-direction: column; + } + + /* Portfolio Aesthetic */ + .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-heading { font-family: 'Space Grotesk', sans-serif; } + + /* Noise Overlay */ + .bg-noise { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + pointer-events: none; z-index: 0; opacity: 0.03; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + } + + /* CRT Scanline */ + .crt-scanline { + position: fixed; top: 0; left: 0; width: 100%; height: 2px; + background: rgba(190, 242, 100, 0.1); opacity: 0.5; + pointer-events: none; z-index: 50; + animation: scanline 8s linear infinite; + } + @keyframes scanline { 0% { top: -10vh; } 100% { top: 110vh; } } + + /* CodeMirror Customization */ + .CodeMirror { + height: 100% !important; + font-family: 'JetBrains Mono', monospace; + font-size: 13px; + background-color: #0c0f16 !important; /* Slightly lighter than pure black */ + color: #f8f8f2; + } + .CodeMirror-gutters { + background-color: #0c0f16 !important; + border-right: 1px solid rgba(255,255,255,0.05) !important; + } + .CodeMirror-linenumber { + color: #555 !important; + } + .CodeMirror-cursor { + border-left: 2px solid var(--accent) !important; + } + .CodeMirror-selected { + background: rgba(190, 242, 100, 0.2) !important; + } + .cm-s-dracula .CodeMirror-activeline-background { + background: rgba(255, 255, 255, 0.03) !important; + } + + /* Scrollbar styling */ + .CodeMirror-scroll::-webkit-scrollbar, + .xterm-viewport::-webkit-scrollbar, + .custom-scrollbar::-webkit-scrollbar { + width: 6px; height: 6px; + } + .CodeMirror-scroll::-webkit-scrollbar-track, + .xterm-viewport::-webkit-scrollbar-track, + .custom-scrollbar::-webkit-scrollbar-track { + background: #050505; + } + .CodeMirror-scroll::-webkit-scrollbar-thumb, + .xterm-viewport::-webkit-scrollbar-thumb, + .custom-scrollbar::-webkit-scrollbar-thumb { + background: #333; border-radius: 3px; + } + + /* Mobile Helper Bar */ + #mobile-helper-bar { + display: none; /* Shown via JS on mobile */ + background: #151515; + border-top: 1px solid rgba(255,255,255,0.1); + padding: 8px; + overflow-x: auto; + white-space: nowrap; + -webkit-overflow-scrolling: touch; + } + @media (max-width: 768px) { + #mobile-helper-bar { display: flex; gap: 8px; } + } + .helper-key { + background: rgba(255,255,255,0.1); + color: var(--accent); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 4px; + padding: 6px 12px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + font-weight: bold; + cursor: pointer; + user-select: none; + } + .helper-key:active { background: var(--accent); color: black; } + + /* Toast Notification */ + .toast { + position: fixed; + bottom: 2rem; + left: 50%; + transform: translateX(-50%) translateY(100px); + background: #1a1a1a; + border: 1px solid var(--accent); + color: var(--accent); + padding: 0.5rem 1.5rem; + border-radius: 9999px; + font-family: 'JetBrains Mono', monospace; + font-size: 0.8rem; + transition: transform 0.3s ease; + z-index: 100; + } + .toast.show { transform: translateX(-50%) translateY(0); } + + /* Connection Dot Pulse */ + .pulse-dot { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); + animation: pulse-white 2s infinite; + } + .pulse-dot.connected { + background-color: #bef264; /* Lime */ + box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); + animation: pulse-lime 2s infinite; + } + .pulse-dot.disconnected { + background-color: #ef4444; /* Red */ + box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); + animation: pulse-red 2s infinite; + } + + @keyframes pulse-lime { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(190, 242, 100, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(190, 242, 100, 0); } + } + @keyframes pulse-red { + 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } + 70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); } + 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } + } + + /* AI Text Overlay */ + .ai-overlay { + position: absolute; + bottom: 10px; + right: 20px; + background: rgba(20, 20, 20, 0.9); + border: 1px solid #ef4444; + color: #fca5a5; + padding: 8px 12px; + border-radius: 6px; + font-family: 'JetBrains Mono', monospace; + font-size: 12px; + z-index: 60; + display: none; + backdrop-filter: blur(4px); + animation: slideIn 0.3s ease-out; + box-shadow: 0 4px 12px rgba(0,0,0,0.5); + } + .ai-overlay.visible { display: flex; align-items: center; gap: 8px; } + + .ai-link { + color: #fff; + text-decoration: underline; + text-decoration-style: dotted; + text-underline-offset: 4px; + cursor: pointer; + font-weight: bold; + transition: color 0.2s; + } + .ai-link:hover { color: #bef264; text-decoration-style: solid; } + + @keyframes slideIn { + from { transform: translateY(20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } + } + + /* Modals (AI & Clear) */ + .modal-overlay { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.8); backdrop-filter: blur(5px); + z-index: 200; display: none; align-items: center; justify-content: center; + } + .modal-overlay.open { display: flex; } + + .modal-content { + background: #0f0f0f; + border: 1px solid var(--accent); + width: 90%; max-width: 600px; + border-radius: 12px; + display: flex; flex-direction: column; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + overflow: hidden; + animation: modalPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + } + + @keyframes modalPop { + 0% { transform: scale(0.9); opacity: 0; } + 100% { transform: scale(1); opacity: 1; } + } + + /* Editor Toolbar Buttons */ + .editor-btn { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + color: #737373; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s; + cursor: pointer; + } + .editor-btn:hover { + background: rgba(255,255,255,0.1); + color: #fff; + border-color: rgba(255,255,255,0.3); + } + .editor-btn.danger:hover { + background: rgba(239, 68, 68, 0.1); + color: #ef4444; + border-color: #ef4444; + } + </style> +</head> +<body class="antialiased selection:bg-lime-300 selection:text-black"> + + <div class="bg-noise"></div> + <div class="crt-scanline"></div> + <div id="toast" class="toast">Link Copied to Clipboard!</div> + + <!-- AI Overlay in Terminal --> + <div id="ai-suggestion" class="ai-overlay"> + <i class="fas fa-exclamation-triangle text-red-500"></i> + <span>Error detected. <span id="ask-ai-link" class="ai-link">Ask AI</span> to fix it.</span> + </div> + + <!-- Clear Confirmation Modal --> + <div id="clear-modal" class="modal-overlay"> + <div class="modal-content max-w-[320px] p-0 border-red-500/50"> + <div class="bg-red-500/10 px-6 py-4 border-b border-red-500/20"> + <h3 class="font-heading font-bold text-lg text-red-500 flex items-center gap-2"> + <i class="fas fa-exclamation-circle"></i> CLEAR CODE + </h3> + </div> + <div class="p-6 text-center"> + <p class="text-neutral-300 text-sm font-sans mb-6">Are you sure you want to clear the editor? This action will remove all current code.</p> + <div class="flex justify-center gap-3"> + <button id="cancel-clear-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all border border-transparent">Cancel</button> + <button id="confirm-clear-btn" class="bg-red-500/10 hover:bg-red-500 hover:text-black text-red-500 border border-red-500/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2"> + <i class="fas fa-trash-alt"></i> Confirm + </button> + </div> + </div> + </div> + </div> + + <!-- AI Fix Modal --> + <div id="ai-modal" class="modal-overlay"> + <div class="modal-content max-h-[80vh]"> + <!-- Modal Header --> + <div class="bg-white/5 px-6 py-4 border-b border-white/10 flex justify-between items-center"> + <h3 class="font-heading font-bold text-lg text-lime-300 flex items-center gap-2"> + <i class="fas fa-robot"></i> AI Diagnosis + </h3> + <button id="close-modal" class="text-neutral-500 hover:text-white transition-colors"> + <i class="fas fa-times"></i> + </button> + </div> + + <!-- Modal Body --> + <div class="p-6 overflow-y-auto custom-scrollbar flex-1"> + <div id="ai-loading" class="hidden flex flex-col items-center justify-center py-8 gap-4"> + <div class="pulse-dot connected" style="width: 12px; height: 12px;"></div> + <p class="font-mono text-neutral-400 text-sm animate-pulse">Analyzing compile error...</p> + </div> + + <div id="ai-result" class="hidden space-y-4"> + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Explanation</h4> + <p id="ai-explanation" class="text-sm text-neutral-200 leading-relaxed font-sans"></p> + </div> + + <div> + <h4 class="font-mono text-xs uppercase text-neutral-500 mb-2">Suggested Fix</h4> + <div class="relative group"> + <pre id="ai-code-preview" class="bg-black/30 border border-white/10 p-3 rounded text-xs font-mono text-lime-100 overflow-x-auto custom-scrollbar"></pre> + </div> + </div> + </div> + + <div id="ai-error-msg" class="hidden text-red-400 text-sm font-mono text-center py-4"></div> + </div> + + <!-- Modal Footer --> + <div class="bg-white/5 px-6 py-4 border-t border-white/10 flex justify-end gap-3"> + <button id="cancel-fix-btn" class="px-4 py-2 rounded text-xs font-mono font-bold uppercase text-neutral-400 hover:text-white hover:bg-white/10 transition-all">Dismiss</button> + <button id="apply-fix-btn" disabled class="bg-lime-300/10 hover:bg-lime-300 hover:text-black text-lime-300 border border-lime-300/20 px-4 py-2 rounded text-xs font-mono font-bold uppercase transition-all flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed"> + <i class="fas fa-check"></i> Apply Fix + </button> + </div> + </div> + </div> + + <!-- Header (Responsive) --> + <header class="h-auto md:h-16 flex flex-col md:flex-row items-center justify-between px-4 py-3 md:px-6 shrink-0 border-b border-white/10 z-20 bg-neutral-900/50 backdrop-blur-md gap-3 md:gap-4"> + + <!-- Top Row: Title & Editor Tools --> + <div class="flex items-center justify-between w-full md:w-auto gap-6"> + <h1 class="text-lg md:text-xl font-heading font-bold text-white tracking-tight flex items-center"> + <span class="text-lime-300 mr-2">//</span>PY.COMPILER + <span id="conn-dot" class="pulse-dot disconnected ml-3" title="Disconnected"></span> + </h1> + + <!-- Editor Tools (Undo/Redo/Clear) --> + <div class="flex items-center gap-2"> + <button id="undo-btn" class="editor-btn" title="Undo (Ctrl+Z)"> + <i class="fas fa-undo text-xs"></i> + </button> + <button id="redo-btn" class="editor-btn" title="Redo (Ctrl+Y)"> + <i class="fas fa-redo text-xs"></i> + </button> + <div class="w-px h-4 bg-white/10 mx-1"></div> + <button id="clear-code-btn" class="editor-btn danger" title="Clear Code"> + <i class="fas fa-times text-xs"></i> + </button> + </div> + + <!-- Mobile Only: Exit Link --> + <a href="./index.html" class="md:hidden font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors ml-auto">[ EXIT ]</a> + </div> + + <!-- Middle: Connection Text --> + <div class="hidden md:flex items-center gap-2 font-mono text-xs text-neutral-500"> + <span id="connection-status">Connecting to server...</span> + </div> + + <!-- Bottom/Right: Buttons --> + <div class="flex items-center gap-2 w-full md:w-auto justify-end"> + <a href="./index.html" class="hidden md:inline font-mono text-[10px] text-neutral-500 hover:text-white uppercase tracking-wider transition-colors mr-2">[ EXIT ]</a> + + <button id="download-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Download .py"> + <i class="fas fa-download"></i> + </button> + + <button id="reset-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Reset Terminal"> + <i class="fas fa-rotate-left"></i> + </button> + + <button id="share-btn" class="bg-white/5 hover:bg-neutral-800 text-white border border-white/10 px-3 py-2 rounded font-mono text-[10px] font-bold uppercase tracking-wider flex items-center justify-center transition-all" title="Share Code"> + <i class="fas fa-share-alt"></i> + </button> + + <button id="run-btn" disabled class="bg-white/5 hover:bg-lime-300 hover:text-black disabled:opacity-50 disabled:cursor-not-allowed text-white border border-white/10 px-4 py-2 rounded font-mono text-xs font-bold uppercase tracking-wider flex items-center gap-2 transition-all flex-1 md:flex-none justify-center shadow-lg shadow-black/50"> + <i class="fas fa-play text-[10px]"></i> <span class="md:hidden lg:inline">EXECUTE</span><span class="hidden md:inline lg:hidden">RUN</span> + </button> + </div> + </header> + + <!-- Main Workspace --> + <div class="flex-1 flex flex-col md:flex-row min-h-0 z-10 relative"> + + <!-- Code Editor --> + <div class="flex-1 flex flex-col h-[60%] md:h-auto min-h-0 border-b md:border-b-0 md:border-r border-white/10 relative group"> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>SRC // main.py</span> + <span class="text-neutral-600">PYTHON 3</span> + </div> + + <!-- CodeMirror Container --> + <div id="editor-container" class="relative bg-[#0c0f16] flex-1 overflow-hidden"> + <textarea id="code-input" class="hidden">import time + +# Simple Clock Preview +print("Current Time:") +print(time.strftime("%H:%M:%S")) +print("Done.")</textarea> + </div> + + <!-- Mobile Helper Bar --> + <div id="mobile-helper-bar"> + <div class="helper-key" data-char=" ">Tab</div> + <div class="helper-key" data-char=":">:</div> + <div class="helper-key" data-char="=">=</div> + <div class="helper-key" data-char="()">()</div> + <div class="helper-key" data-char="[]">[]</div> + <div class="helper-key" data-char="{}">{}</div> + <div class="helper-key" data-char='""'>""</div> + <div class="helper-key" data-char="''">''</div> + <div class="helper-key" data-char="#">#</div> + <div class="helper-key" data-char="+">+</div> + <div class="helper-key" data-char="-">-</div> + <div class="helper-key" data-char="print()">print</div> + </div> + </div> + + <!-- Terminal --> + <div class="flex-1 flex flex-col h-[40%] md:h-auto min-h-0 bg-[#050505]"> + <div class="bg-black/20 px-4 py-2 text-[10px] font-mono text-lime-300 uppercase border-b border-white/10 flex justify-between items-center shrink-0"> + <span>OUT // TERMINAL</span> + <div class="flex gap-2"> + <button id="copy-btn" class="text-neutral-500 hover:text-white transition-colors" title="Copy Output"><i class="fas fa-copy"></i></button> + <span class="text-neutral-600">XTERM.JS</span> + </div> + </div> + <div class="flex-1 relative"> + <div id="terminal-container" class="absolute inset-0 w-full h-full p-2 overflow-hidden"></div> + </div> + </div> + </div> + + <script type="module"> + import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js"; + import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; + import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; + + // --- Firebase Config --- + const firebaseConfig = { + apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw", + authDomain: "compiler-aranag-site.firebaseapp.com", + projectId: "compiler-aranag-site", + storageBucket: "compiler-aranag-site.firebasestorage.app", + messagingSenderId: "558890639400", + appId: "1:558890639400:web:125525d10ab51696a5951d", + measurementId: "G-KH9BGSRRGY" + }; + + // Initialize Firebase + const app = initializeApp(firebaseConfig); + const db = getFirestore(app); + const auth = getAuth(app); + + // Attempt initial sign-in + signInAnonymously(auth).catch((error) => { + console.warn("Auto-Auth failed. App will try unauthenticated access.", error.code); + }); + + // --- Helper: Generate ID --- + function generateId(length = 7) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + } + + // --- DOM Elements --- + const runBtn = document.getElementById('run-btn'); + const resetBtn = document.getElementById('reset-btn'); + const shareBtn = document.getElementById('share-btn'); + const copyBtn = document.getElementById('copy-btn'); + const downloadBtn = document.getElementById('download-btn'); + const connDot = document.getElementById('conn-dot'); + const connectionStatus = document.getElementById('connection-status'); + const toast = document.getElementById('toast'); + + // Editor Tool Elements + const undoBtn = document.getElementById('undo-btn'); + const redoBtn = document.getElementById('redo-btn'); + const clearCodeBtn = document.getElementById('clear-code-btn'); + const clearModal = document.getElementById('clear-modal'); + const cancelClearBtn = document.getElementById('cancel-clear-btn'); + const confirmClearBtn = document.getElementById('confirm-clear-btn'); + + // AI Elements + const aiSuggestion = document.getElementById('ai-suggestion'); + const askAiLink = document.getElementById('ask-ai-link'); + const aiModal = document.getElementById('ai-modal'); + const closeModal = document.getElementById('close-modal'); + const cancelFixBtn = document.getElementById('cancel-fix-btn'); + const applyFixBtn = document.getElementById('apply-fix-btn'); + const aiLoading = document.getElementById('ai-loading'); + const aiResult = document.getElementById('ai-result'); + const aiExplanation = document.getElementById('ai-explanation'); + const aiCodePreview = document.getElementById('ai-code-preview'); + const aiErrorMsg = document.getElementById('ai-error-msg'); + + // --- State --- + let socket = null; + let currentLine = ""; + let startTime = 0; + let lastSuggestedCode = ""; + let outputBuffer = ""; + + // --- CodeMirror Setup --- + const editor = CodeMirror.fromTextArea(document.getElementById("code-input"), { + mode: "python", + theme: "dracula", + lineNumbers: true, + indentUnit: 4, + matchBrackets: true, + autoCloseBrackets: true, + styleActiveLine: true, + inputStyle: "contenteditable", // Better for mobile + viewportMargin: Infinity, + extraKeys: { + "Backspace": function(cm) { + if (cm.somethingSelected()) { + cm.execCommand("delCharBefore"); + return; + } + var cursor = cm.getCursor(); + var line = cm.getLine(cursor.line); + // If cursor is not at start, and everything before it is whitespace + if (cursor.ch > 0 && /^\s+$/.test(line.slice(0, cursor.ch))) { + cm.execCommand("indentLess"); + } else { + cm.execCommand("delCharBefore"); + } + } + }, + }); + + // Fix resize issues + window.addEventListener('resize', () => editor.refresh()); + + // Local Auto-Save + const LOCAL_STORAGE_KEY = 'py_compiler_code_autosave'; + editor.on('change', () => { + localStorage.setItem(LOCAL_STORAGE_KEY, editor.getValue()); + }); + + // Load Auto-Save on Start (if not shared) + const savedCode = localStorage.getItem(LOCAL_STORAGE_KEY); + if (savedCode && !window.location.search.includes('share') && !window.location.search.includes('code')) { + editor.setValue(savedCode); + } + + // --- Editor Toolbar Logic --- + + // Undo/Redo + undoBtn.addEventListener('click', () => { editor.undo(); editor.focus(); }); + redoBtn.addEventListener('click', () => { editor.redo(); editor.focus(); }); + + // Clear Code with Confirmation + clearCodeBtn.addEventListener('click', () => { + clearModal.classList.add('open'); + }); + + cancelClearBtn.addEventListener('click', () => { + clearModal.classList.remove('open'); + }); + + confirmClearBtn.addEventListener('click', () => { + editor.setValue(''); + editor.clearHistory(); // Optional: Clear history if you want a true "fresh start" + editor.focus(); + clearModal.classList.remove('open'); + showToast("Editor Cleared"); + }); + + // Close modal on outside click + clearModal.addEventListener('click', (e) => { + if (e.target === clearModal) clearModal.classList.remove('open'); + }); + + + // --- Mobile Helper Bar --- + document.querySelectorAll('.helper-key').forEach(key => { + key.addEventListener('click', (e) => { + const char = key.getAttribute('data-char'); + const doc = editor.getDoc(); + const cursor = doc.getCursor(); + + if (char === '()') { + doc.replaceRange('()', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '[]') { + doc.replaceRange('[]', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '{}') { + doc.replaceRange('{}', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === '""') { + doc.replaceRange('""', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "''") { + doc.replaceRange("''", cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 1}); + } else if (char === "print()") { + doc.replaceRange('print()', cursor); + doc.setCursor({line: cursor.line, ch: cursor.ch + 6}); + } else { + doc.replaceRange(char, cursor); + } + editor.focus(); + }); + }); + + // --- Download Button --- + downloadBtn.addEventListener('click', () => { + const code = editor.getValue(); + const blob = new Blob([code], { type: 'text/x-python' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'main.py'; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + showToast("Downloaded main.py"); + }); + + window.addEventListener('load', async () => { + const params = new URLSearchParams(window.location.search); + const shareId = params.get('share'); + const sharedCodeOld = params.get('code'); + + if (shareId) { + // Fetch from Firebase + try { + toast.textContent = "Loading shared code..."; + toast.classList.add('show'); + + const docRef = doc(db, "shares", shareId); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + const data = docSnap.data(); + editor.setValue(data.code); + + // Restore Output if it exists + if (data.output && term) { + term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n'); + term.write(data.output.replace(/\n/g, '\r\n')); + term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n'); + } + + toast.textContent = "Code loaded successfully"; + } else { + toast.textContent = "Shared code not found"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } catch (e) { + console.error("Fetch error:", e); + if (e.code === 'permission-denied') { + toast.textContent = "Error: Database Access Denied"; + } else { + toast.textContent = "Error loading code"; + } + setTimeout(() => toast.classList.remove('show'), 3000); + } + } else if (sharedCodeOld) { + // Fallback for Base64 + try { editor.setValue(atob(sharedCodeOld)); } + catch(e) {} + } + setTimeout(connect, 500); + }); + + // --- Terminal Setup --- + const term = new Terminal({ + theme: { + background: '#050505', + foreground: '#f5f5f5', + cursor: '#bef264', + selectionBackground: 'rgba(190, 242, 100, 0.3)', + black: '#050505', + green: '#bef264', + yellow: '#facc15', + red: '#ef4444', + }, + fontFamily: "'JetBrains Mono', monospace", + fontSize: 12, + cursorBlink: true, + convertEol: true + }); + const fitAddon = new FitAddon.FitAddon(); + term.loadAddon(fitAddon); + term.open(document.getElementById('terminal-container')); + fitAddon.fit(); + window.addEventListener('resize', () => fitAddon.fit()); + + // Helper: Get Clean Terminal Output + function getTerminalContent() { + if (!term) return ""; + const buffer = term.buffer.active; + let text = ""; + for (let i = 0; i < buffer.length; i++) { + const line = buffer.getLine(i); + if (line) { + let lineText = line.translateToString(true); + // Filter system messages + if(lineText.trim().startsWith("> [") || + lineText.trim().startsWith("> python") || + lineText.includes("SYSTEM READY") || + lineText.includes("ATTEMPTING") || + lineText.includes("CONNECTION") || + lineText.includes("PREVIOUS OUTPUT") || + lineText.includes("> ----------------") + ) { + continue; + } + text += lineText + "\n"; + } + } + return text.trim(); + } + + // Custom Key Handler for Ctrl+C Copy + term.attachCustomKeyEventHandler((arg) => { + if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") { + const selection = term.getSelection(); + if (selection) { + fallbackCopyTextToClipboard(selection); + return false; + } + } + return true; + }); + + term.write('\x1b[38;2;115;115;115m> SYSTEM READY.\r\n> ATTEMPTING CONNECTION...\x1b[0m\r\n'); + + // --- WebSocket Logic --- + function connect() { + const url = "wss://compiler-z4x4.onrender.com"; + try { socket = new WebSocket(url); } catch (e) { + term.write(`\r\n\x1b[31m> INVALID URL.\x1b[0m\r\n`); + return; + } + + socket.onopen = () => { + connDot.className = "pulse-dot connected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Connected to Server"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-lime-300"; + + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> python3 main.py\r\n`); + runBtn.disabled = false; + }; + + socket.onclose = () => { + connDot.className = "pulse-dot disconnected ml-3"; + if(connectionStatus) connectionStatus.textContent = "Disconnected"; + if(connectionStatus) connectionStatus.className = "hidden md:flex items-center gap-2 font-mono text-xs text-red-500"; + + term.write(`\r\n\x1b[31m> CONNECTION LOST. RECONNECTING...\x1b[0m\r\n`); + runBtn.disabled = true; + setTimeout(connect, 3000); + socket = null; + }; + + socket.onmessage = (event) => { + const msg = JSON.parse(event.data); + if (msg.type === 'stdout') { + let text = msg.data; + outputBuffer += text; + + // Trigger AI Overlay on Error + if (outputBuffer.toLowerCase().includes("error") || outputBuffer.toLowerCase().includes("traceback")) { + aiSuggestion.classList.add('visible'); + } + + if (!text.includes('\r')) { + text = text.replace(/\n/g, '\r\n'); + } + term.write(text); + } else if (msg.type === 'status') { + if (msg.msg.includes("Program finished")) { + const duration = (Date.now() - startTime) / 1000; + term.write(`\r\n\x1b[38;2;115;115;115m[Finished in ${duration.toFixed(3)}s]\x1b[0m\r\n`); + } + } else if (msg.type === 'ai_response') { + handleAiResponse(msg.data); + } else if (msg.type === 'ai_error') { + showAiError(msg.msg); + } + }; + } + + // --- Run Logic --- + runBtn.addEventListener('click', () => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + + // Force focus out to hide mobile keyboards + if (document.activeElement) document.activeElement.blur(); + + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + + // Use Editor Value instead of Textarea + let code = editor.getValue(); + + code = code.replace(/\u00A0/g, " ").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"'); + + startTime = Date.now(); + term.write('\x1b[32m> python3 main.py\x1b[0m\r\n'); + + socket.send(JSON.stringify({ + type: 'run', + code: code, + language: 'python' + })); + + term.focus(); + }); + + // --- AI Feature Logic --- + + // 1. Open Modal and Request AI Fix + askAiLink.addEventListener('click', () => { + const errorContext = getTerminalContent(); + const currentCode = editor.getValue(); + + aiModal.classList.add('open'); + aiLoading.classList.remove('hidden'); + aiResult.classList.add('hidden'); + aiErrorMsg.classList.add('hidden'); + applyFixBtn.disabled = true; + + socket.send(JSON.stringify({ + type: 'ai_fix', + code: currentCode, + error: errorContext, + language: 'python' + })); + }); + + // 2. Handle AI Response + function handleAiResponse(data) { + aiLoading.classList.add('hidden'); + aiResult.classList.remove('hidden'); + + aiExplanation.textContent = data.explanation; + aiCodePreview.textContent = data.fixed_code; + lastSuggestedCode = data.fixed_code; + + applyFixBtn.disabled = false; + } + + // 3. Handle AI Error + function showAiError(msg) { + aiLoading.classList.add('hidden'); + aiErrorMsg.textContent = msg; + aiErrorMsg.classList.remove('hidden'); + } + + // 4. Apply Fix + applyFixBtn.addEventListener('click', () => { + if (lastSuggestedCode) { + editor.setValue(lastSuggestedCode); + closeAiModal(); + showToast("Fix Applied Successfully!"); + aiSuggestion.classList.remove('visible'); + } + }); + + // 5. Modal Controls + function closeAiModal() { + aiModal.classList.remove('open'); + } + closeModal.addEventListener('click', closeAiModal); + cancelFixBtn.addEventListener('click', closeAiModal); + aiModal.addEventListener('click', (e) => { + if (e.target === aiModal) closeAiModal(); + }); + + // --- Reset Logic --- + resetBtn.addEventListener('click', () => { + term.reset(); + currentLine = ""; + outputBuffer = ""; + aiSuggestion.classList.remove('visible'); + term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> python3 main.py\r\n`); + }); + + // --- Share Functionality with Firebase --- + shareBtn.addEventListener('click', async () => { + const originalIcon = shareBtn.innerHTML; + shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; + shareBtn.disabled = true; + + try { + if (!auth.currentUser) { + try { + await signInAnonymously(auth); + } catch (authError) { + console.warn("Anonymous auth failed:", authError.code); + } + } + + const code = editor.getValue(); + const output = getTerminalContent(); + const shareId = generateId(); + + await setDoc(doc(db, "shares", shareId), { + code: code, + language: 'python', + output: output, + createdAt: new Date().toISOString() + }); + + const url = new URL(window.location.href); + url.searchParams.delete('code'); + url.searchParams.set('share', shareId); + const shareUrl = url.toString(); + + if (navigator.share) { + try { + await navigator.share({ + title: document.title, + text: 'Check out my Python code!', + url: shareUrl + }); + } catch (err) { + fallbackCopyTextToClipboard(shareUrl); + } + } else { + fallbackCopyTextToClipboard(shareUrl); + } + } catch (error) { + console.error("Share failed:", error); + if (error.code === 'permission-denied') { + showToast("Share Failed: Access Denied"); + } else { + showToast("Share Failed: " + error.message); + } + } finally { + shareBtn.innerHTML = originalIcon; + shareBtn.disabled = false; + } + }); + + function showToast(msg) { + toast.textContent = msg; + toast.classList.add('show'); + setTimeout(() => toast.classList.remove('show'), 3000); + } + + // --- Smart Copy Function --- + copyBtn.addEventListener('click', () => { + const text = getTerminalContent(); + fallbackCopyTextToClipboard(text); + }); + + function fallbackCopyTextToClipboard(text) { + const textArea = document.createElement("textarea"); + textArea.value = text; + textArea.style.position = "fixed"; + textArea.style.top = "0"; + textArea.style.left = "0"; + textArea.style.opacity = "0"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + document.execCommand('copy'); + showToast("Copied to Clipboard!"); + } catch (err) { + showToast("Copy Failed"); + } + document.body.removeChild(textArea); + } + + // Terminal Input + term.onData((data) => { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + + if (data === '\r') { + term.write('\r\n'); + socket.send(JSON.stringify({ type: 'input', data: currentLine + '\n' })); + currentLine = ""; + } else if (data === '\x7f' || data === '\b') { + if (currentLine.length > 0) { + currentLine = currentLine.slice(0, -1); + term.write('\b \b'); + } + } else { + currentLine += data; + term.write(data); + } + }); + </script> +</body> +</html>+ \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml @@ -4,18 +4,23 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> -<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com --> <url> - <loc>https://ada.amit.is-a.dev/</loc> - <lastmod>2026-01-05T13:26:08+00:00</lastmod> - <priority>1.00</priority> + <loc>https://compiler.amit.is-a.dev/</loc> + <lastmod>2026-01-05T13:27:42+00:00</lastmod> </url> <url> - <loc>https://ada.amit.is-a.dev/terms.html</loc> - <lastmod>2026-01-05T13:26:08+00:00</lastmod> - <priority>0.80</priority> + <loc>https://compiler.amit.is-a.dev/c/</loc> + <lastmod>2026-01-05T13:27:42+00:00</lastmod> +</url> +<url> + <loc>https://compiler.amit.is-a.dev/cpp/</loc> + <lastmod>2026-01-05T13:27:42+00:00</lastmod> +</url> +<url> + <loc>https://compiler.amit.is-a.dev/python/</loc> + <lastmod>2026-01-05T13:27:42+00:00</lastmod> </url>
© notamitgamer • Site Built: 2026-07-21 13:58:23 UTC • git-mirror commit: 1037f62 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror