// BuildChain WebUI let currentTab = 'dash'; let toastTimer = null; async function api(path) { try { return await (await fetch(path)).json(); } catch(e) { showToast('Connection error','error'); return null; } } async function post(path, body) { try { return await (await fetch(path, {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)})).json(); } catch(e) { return null; } } function showToast(msg, type='success') { const el = document.getElementById('toast'); el.textContent = msg; el.className = 'toast ' + type + ' show'; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.className = 'toast', 2500); } function switchTab(tab) { currentTab = tab; document.querySelectorAll('.page').forEach(p => p.classList.remove('active')); document.querySelectorAll('.tab-item').forEach(t => t.classList.remove('active')); document.getElementById('page-' + tab).classList.add('active'); document.querySelector(`[data-tab="${tab}"]`).classList.add('active'); switch(tab) { case 'dash': loadDash(); break; case 'tools': loadTools(); break; case 'test': break; case 'paths': loadPaths(); break; } } function esc(s) { return (s||'').replace(/&/g,'&').replace(//g,'>'); } // ---- Dashboard ---- async function loadDash() { const env = await api('/api/status'); if (env) { document.getElementById('device-info').textContent = `${env.device || '?'} — Android ${env.api_level || '?'} — ${env.arch || '?'}`; document.getElementById('env-device').textContent = env.device || '-'; document.getElementById('env-api').textContent = `API ${env.api_level || '?'}`; document.getElementById('env-arch').textContent = env.arch || '-'; } // Tool status grid const tools = await api('/api/tools'); const grid = document.getElementById('status-grid'); if (tools) { grid.innerHTML = tools.map(t => `
${t.name}
`).join(''); } // Setup status const setup = await api('/api/setup'); const statusEl = document.getElementById('setup-status'); const badgeEl = document.getElementById('setup-badge'); if (setup) { if (setup.complete) { statusEl.textContent = 'All packages installed'; badgeEl.textContent = 'Ready'; badgeEl.className = 'badge badge-ok'; } else { statusEl.textContent = 'Missing: ' + setup.missing.join(', '); badgeEl.textContent = 'Incomplete'; badgeEl.className = 'badge badge-miss'; } } } async function redetect() { showToast('Re-detecting environment...'); await post('/api/redetect', {}); setTimeout(loadDash, 3000); } // ---- Tools ---- async function loadTools() { const tools = await api('/api/tools'); if (!tools) return; const buildTools = tools.filter(t => t.category === 'build-tools'); const platTools = tools.filter(t => t.category === 'platform-tools'); const termuxTools = tools.filter(t => t.category === 'termux'); document.getElementById('build-tools-list').innerHTML = buildTools.map(t => `
${t.name}
${t.path}
${t.exists ? (t.size/1024).toFixed(0)+'K' : 'missing'}
`).join(''); document.getElementById('platform-tools-list').innerHTML = platTools.map(t => `
${t.name}
${t.path}
${t.exists ? (t.size/1024).toFixed(0)+'K' : 'missing'}
`).join(''); document.getElementById('termux-tools-list').innerHTML = termuxTools.map(t => `
${t.name}
${t.category}
${t.exists ? 'installed' : 'not found'}
`).join(''); // BusyBox const bb = await api('/api/busybox'); const bbc = document.getElementById('busybox-info'); if (bb) { bbc.innerHTML = `
${esc(bb.version)}
${bb.count} applets
active
${esc(bb.applets).replace(/,/g, ', ')}
`; } } // ---- Test ---- async function runTest() { const out = document.getElementById('test-output'); out.textContent = 'Running tests...'; const res = await api('/api/test'); if (res && res.output) { out.textContent = res.output; } else { out.textContent = 'Failed to run tests'; } } async function loadLog() { const out = document.getElementById('log-output'); out.textContent = 'Loading...'; const res = await api('/api/log'); if (res && res.log) { out.textContent = res.log; } else { out.textContent = 'No log available'; } } // ---- Paths ---- async function loadPaths() { const paths = await api('/api/paths'); const pc = document.getElementById('path-list'); if (paths) { pc.innerHTML = paths.map((p, i) => `
${esc(p)}
#${i}
`).join(''); } // Env file const envOut = document.getElementById('env-output'); try { const res = await fetch('/api/status'); const env = await res.json(); envOut.textContent = JSON.stringify(env, null, 2); } catch(e) { envOut.textContent = 'Failed to load'; } } // ---- Init ---- document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.tab-item').forEach(t => t.addEventListener('click', () => switchTab(t.dataset.tab))); switchTab('dash'); });