| | |
| | | const confirmed = document.querySelector("#confirmed"); |
| | | const validateButton = document.querySelector("#validate"); |
| | | const startButton = document.querySelector("#start"); |
| | | const retryButton = document.querySelector("#retry"); |
| | | const cancelButton = document.querySelector("#cancel"); |
| | | const phase = document.querySelector("#phase"); |
| | | const progress = document.querySelector("#progress"); |
| | | const detail = document.querySelector("#detail"); |
| | | let startUiLease = false; |
| | | |
| | | function render(state) { |
| | | if (!state) return; |
| | | phase.textContent = `状态:${state.phase}`; |
| | | progress.value = Number.isInteger(state.progress) ? state.progress : 0; |
| | | detail.textContent = state.error_code |
| | | ? `错误码:${state.error_code}` |
| | | : state.formal_filename |
| | | ? `已完成:${state.formal_filename}` |
| | | : ""; |
| | | const active = ["CHECKING", "DOWNLOADING", "MERGING", "VALIDATING", "PUBLISHING"].includes(state.phase); |
| | | cancelButton.hidden = !active; |
| | | retryButton.hidden = state.phase !== "FAILED"; |
| | | retryButton.disabled = startUiLease; |
| | | validateButton.disabled = active || startUiLease; |
| | | startButton.disabled = startUiLease || state.phase !== "READY"; |
| | | } |
| | | |
| | | async function call(action) { |
| | | const response = await chrome.runtime.sendMessage({action}); |
| | | if (!response?.ok) { |
| | | render({phase: "FAILED", progress: 0, error_code: response?.error_code || "E_EXTENSION"}); |
| | | return null; |
| | | } |
| | | render(response.state); |
| | | return response.state; |
| | | } |
| | | |
| | | async function callStart(action) { |
| | | if (startUiLease) return; |
| | | startUiLease = true; |
| | | startButton.disabled = true; |
| | | retryButton.disabled = true; |
| | | validateButton.disabled = true; |
| | | try { |
| | | await call(action); |
| | | } finally { |
| | | startUiLease = false; |
| | | } |
| | | } |
| | | |
| | | validateButton.addEventListener("click", async () => { |
| | | if (!confirmed.checked) { |
| | | render({phase: "FAILED", progress: 0, error_code: "E_VISIBLE_CONFIRMATION"}); |
| | | return; |
| | | } |
| | | const state = await call("validate"); |
| | | startButton.disabled = state?.phase !== "READY"; |
| | | }); |
| | | |
| | | startButton.addEventListener("click", () => callStart("start")); |
| | | retryButton.addEventListener("click", async () => { |
| | | if (!confirmed.checked) { |
| | | render({phase: "FAILED", progress: 0, error_code: "E_VISIBLE_CONFIRMATION"}); |
| | | return; |
| | | } |
| | | await callStart("retry"); |
| | | }); |
| | | cancelButton.addEventListener("click", () => call("cancel")); |
| | | |
| | | call("status"); |
| | | setInterval(() => call("status"), 1000); |
| | | // Historical projection asset retained for exact-set compatibility. |
| | | // The generic queue build does not register a side panel or manual start action. |
| | | document.documentElement.dataset.automation = "host-queue-only"; |