neonsync-cybercoder / index.html
Hayatkhanin06's picture
{
0bfcad5 verified
Raw
History Blame Contribute Delete
10.5 kB
<!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>
/* Cyberpunk Glassmorphism Base */
: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 Effect */
.glass-panel {
backdrop-filter: blur(16px);
background: var(--bg-secondary);
border: 1px solid var(--border-dark);
}
/* Glow Effects */
.glow-effect {
box-shadow: 0 0 15px rgba(124, 58, 237, 0.3);
}
/* Remote Cursor Styling */
.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;
}
/* Cyberpunk UI Elements */
.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);
}
/* Animation */
@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)]">
<!-- Header -->
<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>
<!-- Main Content -->
<div class="flex flex-1 overflow-hidden">
<!-- Sidebar -->
<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>
<!-- Editor Area -->
<div class="flex-1 flex flex-col relative">
<div id="monacoEditor" class="flex-1"></div>
</div>
</div>
<!-- Firebase & Monaco Setup -->
<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}`);
// Initialize user presence with current file
fb.set(cursorRef, {
name: userName,
color: userColor,
currentFile: currentFile
});
// SYNC CODE FROM FIREBASE
fb.onValue(fileRef, (snapshot) => {
const data = snapshot.val();
if (data && data !== editor.getValue()) {
isRemoteUpdate = true;
editor.setValue(data);
isRemoteUpdate = false;
}
});
// BROADCAST CODE TO FIREBASE
editor.onDidChangeModelContent(() => {
if (!isRemoteUpdate) {
fb.set(fileRef, editor.getValue());
}
});
// BROADCAST CURSOR
editor.onDidChangeCursorPosition((e) => {
fb.set(cursorRef, {
line: e.position.lineNumber,
col: e.position.column,
name: userName,
color: userColor,
currentFile: currentFile
});
});
// RENDER REMOTE CURSORS - ONLY FOR CURRENT FILE
const allCursorsRef = fb.ref(db, 'rooms/cyber-room/cursors');
fb.onValue(allCursorsRef, (snapshot) => {
const cursorData = snapshot.val();
if (!cursorData) return;
// Filter cursors for current file only
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;
// Dynamic CSS for name tag
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);
}
// Initialize Feather Icons
document.addEventListener('DOMContentLoaded', () => {
feather.replace();
});
</script>
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
</body>
</html>