// 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.exists ? (t.size/1024).toFixed(0)+'K' : 'missing'}
`).join('');
document.getElementById('platform-tools-list').innerHTML = platTools.map(t => `
${t.exists ? (t.size/1024).toFixed(0)+'K' : 'missing'}
`).join('');
document.getElementById('termux-tools-list').innerHTML = termuxTools.map(t => `
${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) => `
`).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');
});