Spaces:
Paused
Paused
Download static/index.html from ChBysk/AndroidSDK-on-CPU: direct link, hf CLI and curl.
- Browser
- Download file 4.56 kB
-
https://huggingface.co/spaces/ChBysk/AndroidSDK-on-CPU/resolve/main/static/index.html
- Command line
-
hf download hf://spaces/ChBysk/AndroidSDK-on-CPU/static/index.html
-
curl -L -o index.html https://huggingface.co/spaces/ChBysk/AndroidSDK-on-CPU/resolve/main/static/index.html
4.56 kB
| <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> |