| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NeonSync - Cyberpunk Code Editor</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://unpkg.com/feather-icons"></script> |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
| <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> |
| <style> |
| |
| :root { |
| --bg-primary: #050505; |
| --bg-secondary: rgba(20, 20, 30, 0.6); |
| --accent-violet: #7c3aed; |
| --accent-cyan: #06b6d4; |
| --text-primary: #e2e8f0; |
| --text-secondary: #94a3b8; |
| --border-dark: rgba(255, 255, 255, 0.08); |
| } |
| |
| body { |
| font-family: 'Inter', sans-serif; |
| background: var(--bg-primary); |
| color: var(--text-primary); |
| height: 100vh; |
| overflow: hidden; |
| display: flex; |
| flex-direction: column; |
| } |
| |
| |
| .glass-panel { |
| backdrop-filter: blur(16px); |
| background: var(--bg-secondary); |
| border: 1px solid var(--border-dark); |
| } |
| |
| |
| .glow-effect { |
| box-shadow: 0 0 15px rgba(124, 58, 237, 0.3); |
| } |
| |
| |
| .remote-cursor { |
| position: absolute; |
| width: 2px !important; |
| pointer-events: none; |
| z-index: 100; |
| } |
| .remote-cursor-label { |
| position: absolute; |
| top: -18px; |
| left: 0; |
| padding: 1px 4px; |
| font-size: 10px; |
| font-weight: bold; |
| color: #000; |
| border-radius: 3px; |
| white-space: nowrap; |
| z-index: 10; |
| } |
| |
| |
| .cyber-btn { |
| background: linear-gradient(145deg, var(--accent-violet), var(--accent-cyan)); |
| color: white; |
| font-weight: 600; |
| text-transform: uppercase; |
| letter-spacing: 0.05em; |
| border: none; |
| transition: all 0.3s ease; |
| } |
| .cyber-btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 5px 15px rgba(6, 182, 212, 0.4); |
| } |
| |
| |
| @keyframes neon-pulse { |
| 0% { opacity: 1; } |
| 50% { opacity: 0.6; } |
| 100% { opacity: 1; } |
| } |
| .neon-pulse { |
| animation: neon-pulse 2s infinite; |
| } |
| </style> |
| </head> |
| <body class="bg-[var(--bg-primary)] text-[var(--text-primary)]"> |
| |
| <div class="glass-panel h-10 flex items-center px-4 border-b border-[var(--border-dark)]"> |
| <div class="flex items-center gap-2"> |
| <i data-feather="code" class="text-[var(--accent-violet)]"></i> |
| <h1 class="font-bold text-sm uppercase tracking-wider">NEONSYNC</h1> |
| </div> |
| <div id="connectionStatus" class="ml-4 flex items-center text-xs"> |
| <span class="w-2 h-2 rounded-full bg-[var(--accent-cyan)] neon-pulse mr-1"></span> |
| <span class="text-[var(--accent-cyan)]">SYNCED</span> |
| </div> |
| <div class="flex-1"></div> |
| <div id="userAvatars" class="flex gap-2 items-center"></div> |
| </div> |
|
|
| |
| <div class="flex flex-1 overflow-hidden"> |
| |
| <div class="glass-panel w-64 flex flex-col border-r border-[var(--border-dark)]"> |
| <div class="px-4 py-2 text-xs font-bold uppercase tracking-wider text-[var(--text-secondary)]">EXPLORER</div> |
| <div id="fileList" class="flex flex-col"> |
| <div class="flex items-center px-4 py-2 cursor-pointer hover:bg-[rgba(124,58,237,0.1)] transition-colors"> |
| <i data-feather="file-text" class="w-4 h-4 mr-2 text-[var(--accent-cyan)]"></i> |
| <span class="text-sm">main.js</span> |
| </div> |
| <div class="flex items-center px-4 py-2 cursor-pointer hover:bg-[rgba(124,58,237,0.1)] transition-colors"> |
| <i data-feather="file-text" class="w-4 h-4 mr-2 text-[var(--accent-violet)]"></i> |
| <span class="text-sm">style.css</span> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex-1 flex flex-col relative"> |
| <div id="monacoEditor" class="flex-1"></div> |
| </div> |
| </div> |
|
|
| |
| <script type="module"> |
| import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.7.0/firebase-app.js'; |
| import { getDatabase, ref, set, onValue, onDisconnect } from 'https://www.gstatic.com/firebasejs/10.7.0/firebase-database.js'; |
| |
| const firebaseConfig = { |
| apiKey: "AIzaSyDX3fTyEsHJeiTn-2Qmqsq1E03wpx-LnUA", |
| authDomain: "for-linkedin-resume.firebaseapp.com", |
| projectId: "for-linkedin-resume", |
| storageBucket: "for-linkedin-resume.appspot.com", |
| messagingSenderId: "90221086536", |
| appId: "1:90221086536:web:f7110ab8d556e02759957d", |
| databaseURL: "https://for-linkedin-resume-default-rtdb.firebaseio.com" |
| }; |
| |
| const app = initializeApp(firebaseConfig); |
| const db = getDatabase(app); |
| window.db = db; |
| window.fb = { ref, set, onValue, onDisconnect }; |
| </script> |
|
|
| <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js"></script> |
| <script> |
| let editor; |
| let userDecorations = []; |
| let isRemoteUpdate = false; |
| const userId = "user_" + Math.random().toString(36).substr(2, 5); |
| const userName = "CyberDev_" + Math.random().toString(36).substr(2, 3); |
| const userColor = "#" + Math.floor(Math.random()*16777215).toString(16); |
| let currentFile = "main.js"; |
| |
| require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs' } }); |
| require(['vs/editor/editor.main'], function() { |
| editor = monaco.editor.create(document.getElementById('monacoEditor'), { |
| value: "// Welcome to NeonSync\n// Start coding in cyber style...", |
| language: 'javascript', |
| theme: 'vs-dark', |
| automaticLayout: true, |
| fontSize: 14, |
| fontFamily: 'JetBrains Mono', |
| minimap: { enabled: true }, |
| domReadOnly: false, |
| accessibilitySupport: 'on' |
| }); |
| const { db, fb } = window; |
| const roomRef = fb.ref(db, 'rooms/cyber-room'); |
| const fileRef = fb.ref(db, `rooms/cyber-room/files/${currentFile.replace(/\./g, '_')}/code`); |
| const cursorRef = fb.ref(db, `rooms/cyber-room/cursors/${userId}`); |
| |
| |
| fb.set(cursorRef, { |
| name: userName, |
| color: userColor, |
| currentFile: currentFile |
| }); |
| |
| |
| fb.onValue(fileRef, (snapshot) => { |
| const data = snapshot.val(); |
| if (data && data !== editor.getValue()) { |
| isRemoteUpdate = true; |
| editor.setValue(data); |
| isRemoteUpdate = false; |
| } |
| }); |
| |
| |
| editor.onDidChangeModelContent(() => { |
| if (!isRemoteUpdate) { |
| fb.set(fileRef, editor.getValue()); |
| } |
| }); |
| |
| |
| editor.onDidChangeCursorPosition((e) => { |
| fb.set(cursorRef, { |
| line: e.position.lineNumber, |
| col: e.position.column, |
| name: userName, |
| color: userColor, |
| currentFile: currentFile |
| }); |
| }); |
| |
| |
| const allCursorsRef = fb.ref(db, 'rooms/cyber-room/cursors'); |
| fb.onValue(allCursorsRef, (snapshot) => { |
| const cursorData = snapshot.val(); |
| if (!cursorData) return; |
| |
| |
| const filteredCursors = {}; |
| Object.entries(cursorData).forEach(([id, data]) => { |
| if (data.currentFile === currentFile) { |
| filteredCursors[id] = data; |
| } |
| }); |
| |
| updateRemoteCursors(filteredCursors); |
| }); |
| |
| fb.onDisconnect(cursorRef).remove(); |
| }); |
| |
| function updateRemoteCursors(cursorData) { |
| if (!editor || !cursorData) return; |
| const newDecorations = []; |
| |
| Object.entries(cursorData).forEach(([id, data]) => { |
| if (id === userId) return; |
| |
| |
| let styleId = 'cursor-style-' + id; |
| if (!document.getElementById(styleId)) { |
| const style = document.createElement('style'); |
| style.id = styleId; |
| style.innerHTML = `.cursor-${id} { border-left: 2px solid ${data.color}; } |
| .cursor-${id}::after { content: '${data.name}'; position: absolute; top: -18px; background: ${data.color}; color: #000; font-size: 10px; padding: 1px 4px; border-radius: 3px; }`; |
| document.head.appendChild(style); |
| } |
| |
| newDecorations.push({ |
| range: new monaco.Range(data.line, data.col, data.line, data.col), |
| options: { className: `cursor-${id} remote-cursor` } |
| }); |
| }); |
| |
| userDecorations = editor.deltaDecorations(userDecorations, newDecorations); |
| } |
| |
| |
| document.addEventListener('DOMContentLoaded', () => { |
| feather.replace(); |
| }); |
| </script> |
| <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script> |
| </body> |
| </html> |