From 22fe0d6f363b222d3d34c772066d712e9d8d3768 Mon Sep 17 00:00:00 2001 From: gronod Date: Sat, 29 Aug 2026 17:21:39 +0100 Subject: [PATCH] feat(chartread): add Accept/Override button and improve prompt handling for warnings and multi-sheet reads (resolves #137) --- src/index.html | 1 + src/js/chartread.js | 113 ++++++++++++++++++++++++++++++++++++-------- src/styles/main.css | 1 + 3 files changed, 95 insertions(+), 20 deletions(-) diff --git a/src/index.html b/src/index.html index 26a023c..6c5ce1e 100644 --- a/src/index.html +++ b/src/index.html @@ -330,6 +330,7 @@
+ diff --git a/src/js/chartread.js b/src/js/chartread.js index 069fda6..04c5123 100644 --- a/src/js/chartread.js +++ b/src/js/chartread.js @@ -23,6 +23,8 @@ const STATE = { CALIBRATING: "CALIBRATING", AWAITING_STRIP: "AWAITING_STRIP", READING: "READING", + WARNING: "WARNING", + PROMPT_CONTINUE: "PROMPT_CONTINUE", ERROR: "ERROR", FINISHED: "FINISHED", }; @@ -36,6 +38,7 @@ const recordedPasses = []; export function initChartread() { const btnStartRead = document.getElementById("btnStartRead"); const btnCalibrate = document.getElementById("btnCalibrate"); + const btnAccept = document.getElementById("btnAccept"); const btnRetry = document.getElementById("btnRetry"); const btnSkip = document.getElementById("btnSkip"); const btnCancel = document.getElementById("btnCancel"); @@ -174,39 +177,71 @@ export function initChartread() { if (stateLabel) stateLabel.textContent = newState; // Show/hide buttons based on state - btnCalibrate.classList.add("hidden"); - btnRetry.classList.add("hidden"); - btnSkip.classList.add("hidden"); - btnCancel.classList.add("hidden"); - btnStartRead.classList.add("hidden"); + if (btnCalibrate) btnCalibrate.classList.add("hidden"); + if (btnAccept) btnAccept.classList.add("hidden"); + if (btnRetry) btnRetry.classList.add("hidden"); + if (btnSkip) btnSkip.classList.add("hidden"); + if (btnCancel) btnCancel.classList.add("hidden"); + if (btnStartRead) btnStartRead.classList.add("hidden"); switch (newState) { case STATE.IDLE: - btnStartRead.classList.remove("hidden"); + if (btnStartRead) btnStartRead.classList.remove("hidden"); break; case STATE.CALIBRATING: - btnCalibrate.disabled = false; - btnCalibrate.textContent = "✓ Calibrate"; - btnCalibrate.classList.remove("hidden"); - btnCancel.classList.remove("hidden"); + if (btnCalibrate) { + btnCalibrate.disabled = false; + btnCalibrate.textContent = "✓ Calibrate"; + btnCalibrate.classList.remove("hidden"); + } + if (btnCancel) btnCancel.classList.remove("hidden"); break; case STATE.AWAITING_STRIP: - btnRetry.classList.remove("hidden"); - btnSkip.classList.remove("hidden"); - btnCancel.classList.remove("hidden"); + if (btnRetry) { + btnRetry.disabled = false; + btnRetry.textContent = "↻ Retry Strip"; + btnRetry.classList.remove("hidden"); + } + if (btnSkip) btnSkip.classList.remove("hidden"); + if (btnCancel) btnCancel.classList.remove("hidden"); break; case STATE.READING: - btnCancel.classList.remove("hidden"); + if (btnCancel) btnCancel.classList.remove("hidden"); + break; + case STATE.WARNING: + if (btnAccept) { + btnAccept.disabled = false; + btnAccept.textContent = "✓ Accept Strip"; + btnAccept.classList.remove("hidden"); + } + if (btnRetry) { + btnRetry.disabled = false; + btnRetry.textContent = "↻ Retry Strip"; + btnRetry.classList.remove("hidden"); + } + if (btnCancel) btnCancel.classList.remove("hidden"); + break; + case STATE.PROMPT_CONTINUE: + if (btnAccept) { + btnAccept.disabled = false; + btnAccept.textContent = "✓ Continue"; + btnAccept.classList.remove("hidden"); + } + if (btnCancel) btnCancel.classList.remove("hidden"); break; case STATE.ERROR: - btnRetry.classList.remove("hidden"); - btnSkip.classList.remove("hidden"); - btnCancel.classList.remove("hidden"); + if (btnRetry) { + btnRetry.disabled = false; + btnRetry.textContent = "↻ Retry Strip"; + btnRetry.classList.remove("hidden"); + } + if (btnSkip) btnSkip.classList.remove("hidden"); + if (btnCancel) btnCancel.classList.remove("hidden"); break; case STATE.FINISHED: // After a recorded pass, further sheets go through "Measure Another Sheet" if (recordedPasses.length === 0) { - btnStartRead.classList.remove("hidden"); + if (btnStartRead) btnStartRead.classList.remove("hidden"); } break; } @@ -267,7 +302,29 @@ export function initChartread() { const lineLower = line.toLowerCase(); if ( - (lineLower.includes("place") && (lineLower.includes("reference") || lineLower.includes("white") || lineLower.includes("calibrat"))) || + lineLower.includes("(warning)") || + lineLower.includes("use it anyway") || + lineLower.includes("seem to have read strip pass") || + lineLower.includes("unexpected response") || + lineLower.includes("hit return to use it anyway") + ) { + const previousPrompt = promptText ? promptText.textContent.trim() : ""; + const isContinuationPrompt = lineLower.includes("hit return to use it anyway") || lineLower.includes("use it anyway"); + setState(STATE.WARNING); + if (currentState === STATE.WARNING && isContinuationPrompt && previousPrompt && !previousPrompt.includes(line.trim())) { + setPrompt(`${previousPrompt}\n${line.trim()}`); + } else { + setPrompt(line.trim()); + } + } else if ( + lineLower.includes("place sheet") || + lineLower.includes("remove previous sheet") || + (lineLower.includes("hit return to continue") && !lineLower.includes("use it anyway")) + ) { + setState(STATE.PROMPT_CONTINUE); + setPrompt(line.trim()); + } else if ( + (lineLower.includes("place") && (lineLower.includes("reference") || lineLower.includes("white") || lineLower.includes("calibrat") || lineLower.includes("standard"))) || lineLower.includes("hit any key to continue") || lineLower.includes("calibration") ) { @@ -283,7 +340,7 @@ export function initChartread() { } else if (lineLower.includes("reading strip") || lineLower.includes("processing")) { setState(STATE.READING); setPrompt(line.trim()); - } else if (lineLower.includes("error") || lineLower.includes("too fast") || lineLower.includes("too slow") || lineLower.includes("misread")) { + } else if (lineLower.includes("error") || lineLower.includes("too fast") || lineLower.includes("too slow") || lineLower.includes("misread") || lineLower.includes("failed to read")) { setState(STATE.ERROR); setPrompt("⚠️ " + line.trim()); } @@ -464,6 +521,22 @@ export function initChartread() { }); } + // Accept / Continue button — sends newline ("\n") + if (btnAccept) { + btnAccept.addEventListener("click", async () => { + try { + btnAccept.disabled = true; + await invoke("send_stdin", { id: currentProcessId, input: "\n" }); + setState(STATE.READING); + setPrompt("Accepted. Processing..."); + } catch (e) { + console.error("send_stdin error:", e); + btnAccept.disabled = false; + setPrompt(`Failed to send accept signal: ${e}`); + } + }); + } + // Retry button — sends space + newline (same as confirm) if (btnRetry) { btnRetry.addEventListener("click", async () => { diff --git a/src/styles/main.css b/src/styles/main.css index ff99b6f..804b2dc 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -455,6 +455,7 @@ button:disabled { color: #fff; line-height: 1.4; min-height: 2.8em; + white-space: pre-line; } .chartread-actions { -- 2.39.5