// Default Settings const DEFAULT_SETTINGS = { serverUrl: 'http://localhost:8017', isRunning: false, promptSel: '', submitSel: '', resultSel: '', autoStart: false, pollInterval: 4000, logs: [] }; // UI Elements const serverUrlInput = document.getElementById('server-url'); const toggleBtn = document.getElementById('toggle-btn'); const globalStatus = document.getElementById('global-status'); const statusLabel = globalStatus.querySelector('.status-label'); const logConsole = document.getElementById('log-console'); const clearLogsBtn = document.getElementById('clear-logs'); const autoStartInput = document.getElementById('auto-start'); // Advanced inputs const selPromptInput = document.getElementById('sel-prompt'); const selGenerateInput = document.getElementById('sel-generate'); const selModelInput = document.getElementById('sel-model'); const pollIntervalInput = document.getElementById('poll-interval'); // Load settings on startup chrome.storage.local.get(DEFAULT_SETTINGS, (settings) => { serverUrlInput.value = settings.serverUrl; autoStartInput.checked = !!settings.autoStart; selPromptInput.value = settings.promptSel; selGenerateInput.value = settings.submitSel; selModelInput.value = settings.resultSel; pollIntervalInput.value = settings.pollInterval; updateToggleUI(settings.isRunning); renderLogs(settings.logs); updateStatusUI(settings.isRunning ? 'running' : 'idle'); }); // Helper: Append log to UI console function appendLogToUI(log) { const entry = document.createElement('div'); entry.className = `log-entry ${log.level}-log`; const time = new Date(log.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); entry.innerText = `[${time}] ${log.text}`; logConsole.appendChild(entry); logConsole.scrollTop = logConsole.scrollHeight; } // Render entire log list function renderLogs(logs) { logConsole.innerHTML = ''; if (!logs || logs.length === 0) { const entry = document.createElement('div'); entry.className = 'log-entry system-log'; entry.innerText = '[System] No logs yet. Click Start to run.'; logConsole.appendChild(entry); return; } logs.forEach(appendLogToUI); } // Update Toggle Button Style function updateToggleUI(isRunning) { if (isRunning) { toggleBtn.textContent = '⏹ Stop Prompt Mode'; toggleBtn.className = 'btn btn-primary stop-state'; } else { toggleBtn.textContent = '▶ Prompt Mode'; toggleBtn.className = 'btn btn-primary start-state'; } } // DL Mode — one-shot harvest of everything on screen (1K originals), click again to stop. const dlBtn = document.getElementById('dl-btn'); function updateDlUI(active) { dlBtn.textContent = active ? '⏹ Stop DL' : '⬇ DL Mode'; dlBtn.className = 'btn btn-primary ' + (active ? 'stop-state' : 'start-state'); } dlBtn.addEventListener('click', () => { chrome.storage.local.get({ harvestActive: false }, (r) => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (!tabs[0]) return; chrome.tabs.sendMessage(tabs[0].id, { type: r.harvestActive ? 'stopHarvest' : 'startHarvest' }, () => { if (chrome.runtime.lastError) addSystemLog('DL mode: no Flow tab responding — open the Flow project tab first.'); }); }); }); }); chrome.storage.local.get({ harvestActive: false }, (r) => updateDlUI(r.harvestActive)); // Update Global Status indicator function updateStatusUI(status) { globalStatus.className = 'status-indicator'; if (status === 'running') { globalStatus.classList.add('active'); statusLabel.textContent = 'Running'; } else if (status === 'idle') { statusLabel.textContent = 'Idle'; } else if (status === 'error') { globalStatus.classList.add('error'); statusLabel.textContent = 'Error'; } else if (status === 'working') { globalStatus.classList.add('active'); statusLabel.textContent = 'Generating...'; } } // Input Change Handlers function saveSetting(key, value) { chrome.storage.local.set({ [key]: value }); } serverUrlInput.addEventListener('change', (e) => saveSetting('serverUrl', e.target.value)); autoStartInput.addEventListener('change', (e) => saveSetting('autoStart', e.target.checked)); selPromptInput.addEventListener('change', (e) => saveSetting('promptSel', e.target.value)); selGenerateInput.addEventListener('change', (e) => saveSetting('submitSel', e.target.value)); selModelInput.addEventListener('change', (e) => saveSetting('resultSel', e.target.value)); pollIntervalInput.addEventListener('change', (e) => saveSetting('pollInterval', parseInt(e.target.value, 10) || 4000)); // Clear Logs clearLogsBtn.addEventListener('click', () => { chrome.storage.local.set({ logs: [] }, () => { logConsole.innerHTML = ''; }); }); // Copy Logs — grab the whole activity log to the clipboard for pasting into chat. const copyLogsBtn = document.getElementById('copy-logs'); copyLogsBtn.addEventListener('click', () => { chrome.storage.local.get({ logs: [] }, (res) => { const text = (res.logs || []).map(l => `[${new Date(l.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}] ${l.text}` ).join('\n'); const done = () => { copyLogsBtn.textContent = 'Copied!'; setTimeout(() => { copyLogsBtn.textContent = 'Copy'; }, 1200); }; navigator.clipboard.writeText(text).then(done).catch(() => { const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); } catch (e) {} ta.remove(); done(); }); }); }); // Toggle Run Loop toggleBtn.addEventListener('click', () => { chrome.storage.local.get('isRunning', (res) => { const nextState = !res.isRunning; chrome.storage.local.set({ isRunning: nextState }, () => { updateToggleUI(nextState); updateStatusUI(nextState ? 'running' : 'idle'); // Log event const logMsg = nextState ? 'Automation started.' : 'Automation stopped.'; addSystemLog(logMsg); }); }); }); // Add System Log Helper function addSystemLog(text) { chrome.storage.local.get({ logs: [] }, (res) => { const newLog = { level: 'system', text: text, timestamp: Date.now() }; const updated = [...res.logs, newLog].slice(-300); // keep enough for a harvest debug chrome.storage.local.set({ logs: updated }, () => { appendLogToUI(newLog); }); }); } // Listen for storage changes to sync UI across multiple popup openings chrome.storage.onChanged.addListener((changes, area) => { if (area === 'local') { if (changes.isRunning) { updateToggleUI(changes.isRunning.newValue); updateStatusUI(changes.isRunning.newValue ? 'running' : 'idle'); } if (changes.status) { updateStatusUI(changes.status.newValue); } if (changes.harvestActive) { updateDlUI(changes.harvestActive.newValue); } if (changes.logs) { // Re-render logs if they changed (e.g. from background content script) renderLogs(changes.logs.newValue); } } });