AndroidSDK-on-CPU / static /index.html
ChBysk's picture
Create static/index.html
6431502 verified
Raw History Blame Contribute Delete
4.56 kB
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Android Build UI</title>
<style>
body { font-family: Arial, sans-serif; margin: 24px; max-width: 800px; }
label { display:block; margin-top:12px; }
input, textarea, select { width:100%; padding:8px; box-sizing:border-box; }
button { margin-top:12px; padding:10px 16px; }
#logs { white-space: pre-wrap; background:#111; color:#eee; padding:12px; height:320px; overflow:auto; margin-top:12px; }
.artifact { margin-top:8px; }
</style>
</head>
<body>
<h2>Android Build UI (proxy)</h2>
<p>Provide repo URL (or upload ZIP), branch/ref, and the Gradle task to run (e.g., assembleDebug).</p>
<label>Build Runner API Key (or leave blank to use server default)</label>
<input id="api_key" placeholder="X-API-KEY value" />
<label>Repo URL</label>
<input id="repo_url" placeholder="https://github.com/your/repo.git" />
<label>Git ref / branch</label>
<input id="git_ref" value="main" />
<label>Gradle task</label>
<input id="gradle_task" value="assembleDebug" />
<label>Or upload zip (repo snapshot)</label>
<input id="file" type="file" accept=".zip" />
<button id="start">Start Build</button>
<h3>Job</h3>
<div id="job_area">No job yet.</div>
<h3>Logs</h3>
<div id="logs">—</div>
<h3>Artifacts</h3>
<div id="artifacts"></div>
<script>
const buildUrl = "/build";
const statusBase = "/status";
const logsBase = "/logs";
const artifactsBase = "/artifacts";
document.getElementById("start").addEventListener("click", async () => {
const api_key = document.getElementById("api_key").value;
const repo_url = document.getElementById("repo_url").value;
const git_ref = document.getElementById("git_ref").value;
const gradle_task = document.getElementById("gradle_task").value;
const fileInput = document.getElementById("file");
let resp;
if (fileInput.files.length > 0) {
const fd = new FormData();
fd.append("file", fileInput.files[0]);
fd.append("gradle_task", gradle_task);
fd.append("git_ref", git_ref);
if (api_key) fd.append("api_key", api_key);
resp = await fetch(buildUrl, { method: "POST", body: fd });
} else {
const body = { repo_url, git_ref, gradle_task };
resp = await fetch(buildUrl, { method: "POST", headers: { "Content-Type": "application/json", ...(api_key ? {"X-API-KEY": api_key} : {}) }, body: JSON.stringify(body) });
}
const data = await resp.json();
if (!resp.ok) {
alert("Error starting build: " + JSON.stringify(data));
return;
}
const jobId = data.job_id;
document.getElementById("job_area").innerText = "Started job: " + jobId;
pollStatus(jobId, api_key);
streamLogs(jobId, api_key);
});
async function pollStatus(jobId, api_key) {
const area = document.getElementById("artifacts");
area.innerHTML = "Polling status...";
const interval = setInterval(async () => {
const resp = await fetch(`${statusBase}/${jobId}`, { headers: api_key ? {"X-API-KEY": api_key} : {} });
const data = await resp.json();
if (!resp.ok) {
area.innerText = "Error: " + JSON.stringify(data);
clearInterval(interval);
return;
}
area.innerHTML = "";
area.appendChild(document.createTextNode("Status: " + data.status + (data.exit_code !== undefined ? " (exit " + data.exit_code + ")" : "")));
if (data.artifacts && data.artifacts.length) {
data.artifacts.forEach(a => {
const d = document.createElement("div");
d.className = "artifact";
const link = document.createElement("a");
link.href = a.url;
link.innerText = a.name;
link.target = "_blank";
d.appendChild(link);
area.appendChild(d);
});
}
if (data.status === "success" || data.status === "failed") {
clearInterval(interval);
}
}, 3000);
}
async function streamLogs(jobId, api_key) {
const out = document.getElementById("logs");
out.innerText = "Connecting logs...\n";
try {
const resp = await fetch(`${logsBase}/${jobId}`, { headers: api_key ? {"X-API-KEY": api_key} : {} });
if (!resp.ok) {
out.innerText = "No logs (status " + resp.status + ")";
return;
}
const reader = resp.body.getReader();
const decoder = new TextDecoder();
while(true) {
const { done, value } = await reader.read();
if (done) break;
out.innerText += decoder.decode(value);
out.scrollTop = out.scrollHeight;
}
} catch (e) {
out.innerText += "\nLog stream error: " + e;
}
}
</script>
</body>
</html>