Explain This
Find Bugs
Refactor
Add Comments
`, 'style.css': `body { background: #0c0c12; color: #e0e0e0; } h1 { color: #00AFFF; }`, 'otonai.js': `console.log('OTON AI Script Loaded.');`, 'hero_image.png': `Hero Image`, }; let openAssets = new Set(); let activeFile = null; let showPreview = true; const addChatMessage = (message, speaker) => { const msgDiv = document.createElement('div'); msgDiv.className = 'chat-message'; const speakerSpan = document.createElement('span'); speakerSpan.className = `speaker speaker-${speaker}`; speakerSpan.textContent = `${speaker}: `; msgDiv.appendChild(speakerSpan); const messageNode = document.createTextNode(message); msgDiv.appendChild(messageNode); chatMessages.appendChild(msgDiv); chatMessages.scrollTop = chatMessages.scrollHeight; }; const handleUserChat = async () => { const query = chatInput.value.trim(); if (!query) return; addChatMessage(query, 'User'); chatInput.value = ''; chatInput.disabled = true; chatSendButton.disabled = true; try { const result = await processUserQuery({ query }); addChatMessage(result.data.response, 'OTON'); } catch (error) { console.error("Error calling OTON:", error); addChatMessage("Error connecting to the Nexus Core.", 'System'); } finally { chatInput.disabled = false; chatSendButton.disabled = false; chatInput.focus(); } }; const callOtonWithContext = (action) => { if (!activeFile || !fileContent[activeFile]) { addChatMessage("Please select a file with content to analyze.", "System"); return; } const code = fileContent[activeFile]; const prompt = `Based on the file "${activeFile}", ${action} the following code:\n\n\`\`\`\n${code}\n\`\`\``; chatInput.value = prompt; handleUserChat(); }; const openOrFocusAsset = (fileName) => { openAssets.add(fileName); setActiveTab(fileName); }; const closeAsset = (fileName) => { openAssets.delete(fileName); if (activeFile === fileName) { activeFile = openAssets.size > 0 ? Array.from(openAssets)[openAssets.size - 1] : null; } renderUI(); }; const setActiveTab = (fileName) => { activeFile = fileName; renderUI(); }; const createPane = (fileName) => { const pane = document.createElement('div'); pane.className = 'pane'; const header = document.createElement('div'); header.className = 'pane-header'; header.textContent = fileName; const content = document.createElement('div'); content.className = 'pane-content'; const fileExtension = fileName.split('.').pop(); if (['png', 'jpg', 'jpeg', 'gif'].includes(fileExtension)) { content.innerHTML = fileContent[fileName]; } else { const pre = document.createElement('pre'); const code = document.createElement('code'); code.textContent = fileContent[fileName] || ''; pre.appendChild(code); content.appendChild(pre); } pane.appendChild(header); pane.appendChild(content); return pane; }; const createLivePreview = () => { const previewPane = createPane('Live Preview'); const iframe = document.createElement('iframe'); iframe.style.width = '100%'; iframe.style.height = '100%'; iframe.style.border = 'none'; iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin'); previewPane.querySelector('.pane-content').innerHTML = ''; previewPane.querySelector('.pane-content').style.padding = '0'; previewPane.querySelector('.pane-content').appendChild(iframe); const html = fileContent['index.html'] || ''; const css = fileContent['style.css'] || ''; const js = fileContent['otonai.js'] || ''; const fullHtml = `${html.replace(/.*?<\/script>/g, '')}`; iframe.srcdoc = fullHtml; return previewPane; }; const renderTabs = () => { assetNodesContainer.innerHTML = ''; openAssets.forEach(fileName => { const node = document.createElement('div'); node.className = `asset-node flex items-center gap-2 ${activeFile === fileName ? 'active' : ''}`; node.textContent = fileName; const closeBtn = document.createElement('span'); closeBtn.innerHTML = '×'; closeBtn.className = 'ml-2 hover:bg-white/20 rounded-full px-1.5 cursor-pointer'; closeBtn.onclick = (e) => { e.stopPropagation(); closeAsset(fileName); }; node.appendChild(closeBtn); node.onclick = () => setActiveTab(fileName); assetNodesContainer.appendChild(node); }); }; const renderPanes = () => { mainCanvas.innerHTML = ''; if (openAssets.size === 0) { mainCanvas.innerHTML = '

Select a file to begin.

'; return; } const canShowPreview = openAssets.has('index.html') && showPreview; if (canShowPreview && window.innerWidth >= 768) { mainCanvas.style.gridTemplateColumns = '1fr 1fr'; const activePane = activeFile ? createPane(activeFile) : createPane(Array.from(openAssets)[0]); mainCanvas.appendChild(activePane); mainCanvas.appendChild(createLivePreview()); } else { mainCanvas.style.gridTemplateColumns = '1fr'; if (activeFile) mainCanvas.appendChild(createPane(activeFile)); } }; const renderUI = () => { renderTabs(); renderPanes(); }; // Event Listeners document.querySelectorAll('.asset-item').forEach(item => { item.addEventListener('click', () => openOrFocusAsset(item.dataset.file)); }); previewButton.addEventListener('click', () => { showPreview = !showPreview; previewButton.classList.toggle('active', showPreview); renderPanes(); }); otonButton.addEventListener('click', (e) => { e.stopPropagation(); if (activeFile) { contextMenu.style.display = 'block'; const rect = otonButton.getBoundingClientRect(); contextMenu.style.left = `${rect.right - contextMenu.offsetWidth}px`; contextMenu.style.top = `${rect.bottom + 5}px`; } else { addChatMessage("Please select a file to use the AI assistant.", "System"); } }); contextMenu.addEventListener('click', (e) => { const action = e.target.dataset.action; if (action) { callOtonWithContext(action); contextMenu.style.display = 'none'; } }); document.addEventListener('click', () => contextMenu.style.display = 'none'); chatSendButton.addEventListener('click', handleUserChat); chatInput.addEventListener('keypress', (e) => e.key === 'Enter' && handleUserChat()); window.addEventListener('resize', renderPanes); // Initial Load openOrFocusAsset('index.html'); addChatMessage("Welcome to the OTON Workspace. Select a file and ask me anything.", "OTON"); } onAuthStateChanged(auth, (user) => { if (user) { initializeCanvasApp(); } else { window.location.href = './login.html'; } });