feat: add Auto Run mode for full automated flow

- Background: add step completion waiting (promise-based), autoRun/resumeAutoRun
  chains steps 1→2 (pause for email) → 3→4→5→6→7→8→9 automatically
- Side Panel: add "Auto Run" button and "Continue Auto" bar for email pause point
- signup-page.js: add step 8 handler to click "继续" on OAuth consent page
- Fix all steps to reportComplete before form submit (prevents connection loss on navigation)
- qq-mail.js: fallback after 3 attempts to first matching email
- vps-panel.js: step 9 waits for "认证成功!" status badge
This commit is contained in:
unknown
2026-04-05 09:42:17 +08:00
parent 887709e824
commit 1c1e589bdc
7 changed files with 743 additions and 431 deletions
+70 -1
View File
@@ -128,11 +128,30 @@ function appendLog(entry) {
const levelLabel = entry.level.toUpperCase().padEnd(5);
const line = document.createElement('div');
line.className = `log-${entry.level}`;
line.textContent = `${time} [${levelLabel}] ${entry.message}`;
// Extract step number from message (e.g., "Step 4: ..." or "[vps-panel] Step 1: ...")
const stepMatch = entry.message.match(/Step (\d)/);
const stepNum = stepMatch ? stepMatch[1] : null;
// Build rich HTML
let html = `<span class="log-time">${time}</span> `;
html += `<span class="log-level log-level-${entry.level}">[${levelLabel}]</span> `;
if (stepNum) {
html += `<span class="log-step-tag step-${stepNum}">S${stepNum}</span>`;
}
html += `<span>${escapeHtml(entry.message)}</span>`;
line.innerHTML = html;
logArea.appendChild(line);
logArea.scrollTop = logArea.scrollHeight;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ============================================================
// Button Handlers
// ============================================================
@@ -163,6 +182,32 @@ document.querySelectorAll('.step-btn').forEach(btn => {
});
});
// Auto Run button
const btnAutoRun = document.getElementById('btn-auto-run');
const btnAutoContinue = document.getElementById('btn-auto-continue');
const autoContinueBar = document.getElementById('auto-continue-bar');
btnAutoRun.addEventListener('click', async () => {
btnAutoRun.disabled = true;
btnAutoRun.textContent = 'Running...';
await chrome.runtime.sendMessage({ type: 'AUTO_RUN', source: 'sidepanel' });
});
btnAutoContinue.addEventListener('click', async () => {
const email = inputEmail.value.trim();
if (!email) {
appendLog({ message: 'Please paste DuckDuckGo email first!', level: 'error', timestamp: Date.now() });
return;
}
autoContinueBar.style.display = 'none';
btnAutoRun.textContent = 'Running...';
await chrome.runtime.sendMessage({
type: 'RESUME_AUTO_RUN',
source: 'sidepanel',
payload: { email },
});
});
// Reset button
btnReset.addEventListener('click', async () => {
if (confirm('Reset all steps and data?')) {
@@ -177,6 +222,9 @@ btnReset.addEventListener('click', async () => {
displayStatus.classList.remove('has-value');
logArea.innerHTML = '';
document.querySelectorAll('.step-status').forEach(el => el.textContent = '\u2B1A');
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
updateButtonStates();
}
});
@@ -222,6 +270,27 @@ chrome.runtime.onMessage.addListener((message) => {
}
break;
}
case 'AUTO_RUN_STATUS': {
const { phase } = message.payload;
switch (phase) {
case 'waiting_email':
autoContinueBar.style.display = 'flex';
btnAutoRun.textContent = 'Waiting...';
break;
case 'complete':
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
break;
case 'stopped':
btnAutoRun.disabled = false;
btnAutoRun.textContent = 'Auto Run';
autoContinueBar.style.display = 'none';
break;
}
break;
}
}
});