Spaces:
Sleeping
Sleeping
| // static/js/settings.js v7 | |
| var currentAccent = '#ffc107'; | |
| function switchPanel(id, el) { | |
| document.querySelectorAll('.settings-panel').forEach(function(p) { p.classList.remove('active'); }); | |
| document.getElementById(id).classList.add('active'); | |
| document.querySelectorAll('.settings-tab').forEach(function(t) { t.classList.remove('active'); }); | |
| el.classList.add('active'); | |
| } | |
| function setAccent(hex, el) { | |
| currentAccent = hex; | |
| document.querySelectorAll('.swatch').forEach(function(s) { s.classList.remove('active'); }); | |
| if (el) el.classList.add('active'); | |
| document.getElementById('custom-accent').value = hex; | |
| previewSettings(); | |
| } | |
| function previewSettings() { | |
| document.documentElement.style.setProperty('--accent', currentAccent); | |
| document.documentElement.style.setProperty('--accent-dim', currentAccent + '1f'); | |
| document.documentElement.style.setProperty('--accent-glow', currentAccent + '40'); | |
| var theme = document.getElementById('setting-theme-mode').value; | |
| var isLight = theme === 'light'; | |
| document.documentElement.classList.toggle('light', isLight); | |
| localStorage.setItem('theme', isLight ? 'light' : 'dark'); | |
| var icon = document.getElementById('theme-icon'); | |
| if (icon) icon.className = isLight ? 'fa-solid fa-sun' : 'fa-solid fa-moon'; | |
| var bgUrl = document.getElementById('setting-bg-url').value.trim(); | |
| document.body.style.backgroundImage = bgUrl ? 'url(' + bgUrl + ')' : 'none'; | |
| if (bgUrl) { document.body.style.backgroundSize = 'cover'; document.body.style.backgroundPosition = 'center'; } | |
| var ef = document.getElementById('setting-editor-font').value; | |
| var es = document.getElementById('setting-editor-font-size').value; | |
| var pm = document.getElementById('setting-editor-minimap').value === 'true'; | |
| document.documentElement.style.setProperty('--font-mono', ef); | |
| if (typeof editor !== 'undefined' && editor) { | |
| editor.setOptions({ fontFamily: ef, fontSize: es, showPrintMargin: pm }); | |
| editor.setTheme(isLight ? 'ace/theme/github' : 'ace/theme/tomorrow_night_eighties'); | |
| } | |
| var ts = document.getElementById('setting-terminal-font-size').value; | |
| var to = document.getElementById('term-output'); | |
| if (to) to.style.fontSize = ts; | |
| } | |
| async function saveSettings() { | |
| var btn = document.getElementById('save-settings-btn'); | |
| btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Saving...'; | |
| previewSettings(); | |
| var d = { | |
| theme: document.getElementById('setting-theme-mode').value, accent: currentAccent, | |
| bgUrl: document.getElementById('setting-bg-url').value, | |
| editorFont: document.getElementById('setting-editor-font').value, | |
| editorSize: document.getElementById('setting-editor-font-size').value, | |
| editorMinimap: document.getElementById('setting-editor-minimap').value, | |
| termSize: document.getElementById('setting-terminal-font-size').value, | |
| openrouterKey: document.getElementById('setting-openrouter-key').value, | |
| nvidiaKey: document.getElementById('setting-nvidia-key').value, | |
| aiModel: document.getElementById('setting-ai-model').value, | |
| aiPrompt: document.getElementById('setting-ai-prompt').value | |
| }; | |
| try { | |
| var res = await fetch('/api/settings', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token: currentToken, settings: d}) }); | |
| var data = await res.json(); | |
| if (data.success) { btn.innerHTML = '<i class="fa-solid fa-check"></i> Saved'; showToast('Settings saved', 'success'); setTimeout(function() { btn.innerHTML = 'Save Settings'; }, 2000); } | |
| else showToast('Failed', 'error'); | |
| } catch (e) { showToast('Network error', 'error'); } | |
| btn.innerHTML = 'Save Settings'; | |
| } | |
| async function loadSettings() { | |
| if (!currentUser) return; | |
| var u = document.getElementById('setting-username'), a = document.getElementById('profile-avatar'); | |
| if (u) u.value = currentUser; | |
| if (a) a.textContent = currentUser.charAt(0).toUpperCase(); | |
| var t = localStorage.getItem('theme'); | |
| if (t) document.getElementById('setting-theme-mode').value = t; | |
| previewSettings(); | |
| } | |
| function updateAIModelBadge() { | |
| var el = document.getElementById('setting-ai-model'), b = document.getElementById('current-ai-model'); | |
| if (el && b) b.textContent = el.options[el.selectedIndex].text; | |
| } | |
| async function syncHuggingFace() { | |
| var btn = document.getElementById('hf-sync-btn'), st = document.getElementById('sync-status'); | |
| btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Syncing...'; | |
| btn.disabled = true; | |
| try { | |
| var res = await fetch('/api/sync/hf', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token: currentToken}) }); | |
| var data = await res.json(); | |
| if (data.success) { showToast('Synced!', 'success'); st.textContent = data.message; st.style.color = 'var(--success)'; } | |
| else { showToast('Failed', 'error'); st.textContent = data.error; st.style.color = 'var(--error)'; } | |
| } catch (e) { showToast('Network error', 'error'); st.textContent = 'Error'; st.style.color = 'var(--error)'; } | |
| btn.innerHTML = '<i class="fa-solid fa-rotate"></i> Sync to HF Bucket'; | |
| btn.disabled = false; | |
| } | |
| function downloadWorkspace() { if (currentToken) window.location.href = '/api/export/' + currentToken; } | |
| function toggleGithubModal() { | |
| var m = document.getElementById('github-import-modal'); | |
| if (m.style.display === 'none' || !m.style.display) { m.style.display = 'block'; document.getElementById('github-repo-url').focus(); } | |
| else { m.style.display = 'none'; document.getElementById('github-repo-url').value = ''; document.getElementById('github-pat-token').value = ''; } | |
| } | |
| async function importGithubRepo() { | |
| if (!currentToken) return; | |
| var url = document.getElementById('github-repo-url').value.trim(); | |
| var tok = document.getElementById('github-pat-token').value.trim(); | |
| if (!url || !url.startsWith('https://github.com/')) { showToast('Enter valid GitHub URL', 'warning'); return; } | |
| toggleGithubModal(); | |
| showToast('Cloning...', 'info'); | |
| try { | |
| var payload = { token: currentToken, github_url: url }; | |
| if (tok) payload.github_token = tok; | |
| var res = await fetch('/api/import/github', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload) }); | |
| var data = await res.json(); | |
| if (data.success) { showToast('Imported!', 'success'); setTimeout(function() { location.reload(); }, 1500); } | |
| else showToast('Failed: ' + data.error, 'error'); | |
| } catch (e) { showToast('Error', 'error'); } | |
| } | |