Add status progress for batch tool operations

This commit is contained in:
2026-05-29 13:40:17 +08:00
parent 5625d94106
commit 80f155dfe8
14 changed files with 307 additions and 65 deletions

View File

@@ -113,6 +113,25 @@ const statusEl = document.getElementById('status');
const resultsEl = document.getElementById('results');
const sourceSelectionEl = document.getElementById('sourceSelection');
async function readJSONStream(response, handle) {
if (!response.ok || !response.body) throw new Error('Request failed.');
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
let newline;
while ((newline = buffer.indexOf('\n')) >= 0) {
const line = buffer.slice(0, newline);
buffer = buffer.slice(newline + 1);
if (line.trim()) handle(JSON.parse(line));
}
}
if (buffer.trim()) handle(JSON.parse(buffer));
}
function updateConvertBtn() {
const hasNet = [...document.querySelectorAll('.net-cb')].some(c => c.checked);
convertBtn.disabled = !srcEl.value || !outEl.value || !baseNameEl.value.trim() || !hasNet;
@@ -215,9 +234,24 @@ document.getElementById('convert').addEventListener('click', async () => {
headers:{'Content-Type':'application/json'},
body: JSON.stringify({ sourcePath: srcEl.value, outputDir: outEl.value, baseName: baseNameEl.value, networks })
});
const msg = await res.json();
let msg = null;
try {
await readJSONStream(res, (event) => {
if (event.type === 'status') {
statusEl.textContent = event.message;
statusEl.classList.add('is-busy');
} else if (event.type === 'done') {
msg = event;
} else if (event.type === 'error') {
msg = { error: event.message, results: event.results || [] };
}
});
} catch (e) {
msg = { error: e.message || e, results: [] };
}
convertBtn.disabled = false;
updateConvertBtn();
if (!msg) { msg = { error: 'No response.', results: [] }; }
if (msg.error) { statusEl.classList.remove('is-busy'); statusEl.textContent = 'Error: ' + msg.error; return; }
const results = msg.results || [];
const ok = results.filter(r => r.ok).length;
@@ -256,33 +290,37 @@ func PlayworksPickOutput(w http.ResponseWriter, r *http.Request) {
}
func PlayworksConvert(w http.ResponseWriter, r *http.Request) {
send := newJSONStream(w)
var opts playworksConvertOptions
if err := json.NewDecoder(r.Body).Decode(&opts); err != nil {
writeJSON(w, map[string]any{"results": []playworksNetworkResult{}, "error": err.Error()})
send(map[string]any{"type": "error", "message": err.Error(), "results": []playworksNetworkResult{}})
return
}
if !fileExists(opts.SourcePath) {
writeJSON(w, map[string]any{"results": []playworksNetworkResult{}, "error": "Source file not found."})
send(map[string]any{"type": "error", "message": "Source file not found.", "results": []playworksNetworkResult{}})
return
}
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
writeJSON(w, map[string]any{"results": []playworksNetworkResult{}, "error": "Could not create output folder."})
send(map[string]any{"type": "error", "message": "Could not create output folder.", "results": []playworksNetworkResult{}})
return
}
send(map[string]any{"type": "status", "message": "Reading source HTML..."})
data, err := os.ReadFile(opts.SourcePath)
if err != nil {
writeJSON(w, map[string]any{"results": []playworksNetworkResult{}, "error": "Could not read source: " + err.Error()})
send(map[string]any{"type": "error", "message": "Could not read source: " + err.Error(), "results": []playworksNetworkResult{}})
return
}
results := []playworksNetworkResult{}
send(map[string]any{"type": "status", "message": "Converting Unity..."})
unityPath, err := copyPlayworksUnityInput(data, opts)
if err != nil {
results = append(results, playworksNetworkResult{Network: "un", OK: false, Error: err.Error()})
} else {
results = append(results, playworksNetworkResult{Network: "un", File: unityPath, OK: true})
}
for _, network := range opts.Networks {
for i, network := range opts.Networks {
send(map[string]any{"type": "status", "message": fmt.Sprintf("Converting %d/%d %s", i+1, len(opts.Networks), network)})
filePath, err := convertPlayworksNetwork(string(data), opts, network)
if err != nil {
results = append(results, playworksNetworkResult{Network: network, OK: false, Error: err.Error()})
@@ -290,7 +328,7 @@ func PlayworksConvert(w http.ResponseWriter, r *http.Request) {
}
results = append(results, playworksNetworkResult{Network: network, File: filePath, OK: true})
}
writeJSON(w, map[string]any{"results": results})
send(map[string]any{"type": "done", "results": results})
}
var playworksSuffixRx = regexp.MustCompile(`_(?:un|al|is|fb|gg|ap|mo|vu|mtg|tt)$`)