Files
pbakaus_impeccable/extension/popup/popup.js
T
046a8593f5 Fix: surface scan failures in extension popup for local files (#261)
* Fix: surface scan failures in extension popup for local files

Scanning a local file:// page with "Allow access to file URLs" off left
the popup stuck on "Scanning..." because the blocked content-script
injection returned silently. ensureContentScriptInjected() now returns the
real error, and sendScanToTab() sends a scan-failed message that the popup
renders as a small line, with a permission hint shown only for file:// tabs.

Fixes #258

Co-authored-by: Cursor <cursoragent@cursor.com>

* Improve: report the actual error when a non-file scan fails

The generic "This page can't be scanned." gave no reason. Non-file failures
now read "Couldn't scan this page: <error>" so the user sees what Chrome
reported instead of a dead end.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix: scope popup broadcasts to the active tab

The popup acted on every findings-updated / scan-failed / overlays broadcast
regardless of which tab it targeted, so a background or DevTools-driven
rescan on another tab could reset the button or show a spurious error. Cache
the active tab id and ignore broadcasts for other tabs.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 21:49:16 -07:00

85 lines
3.1 KiB
JavaScript

/**
* Impeccable DevTools Extension - Popup
*
* Quick controls: scan, toggle overlays, and see finding count.
*/
const countNumber = document.getElementById('count-number');
const countLabel = document.getElementById('count-label');
const btnScan = document.getElementById('btn-scan');
const btnToggle = document.getElementById('btn-toggle');
const scanError = document.getElementById('scan-error');
let overlaysVisible = true;
// The popup only ever reflects the active tab. Broadcasts from the service
// worker carry a tabId, so we cache the active one and ignore updates meant
// for other tabs (e.g. a DevTools-driven rescan failing on a background tab).
let activeTabId = null;
async function getActiveTabId() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
return tab?.id;
}
function updateFromState(state) {
if (!state) return;
const count = state.findings?.reduce((sum, f) => sum + f.findings.length, 0) || 0;
countNumber.textContent = String(count);
countNumber.classList.toggle('has-findings', count > 0);
countLabel.textContent = count === 1 ? 'anti-pattern' : 'anti-patterns';
overlaysVisible = state.overlaysVisible !== false;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
}
async function loadState() {
const tabId = await getActiveTabId();
if (!tabId) return;
activeTabId = tabId;
chrome.runtime.sendMessage({ action: 'get-state', tabId }, updateFromState);
}
// Listen for real-time updates from service worker
chrome.runtime.onMessage.addListener((msg) => {
// Ignore broadcasts for a tab other than the one this popup is showing.
if (msg.tabId != null && activeTabId != null && msg.tabId !== activeTabId) return;
if (msg.action === 'findings-updated') {
const count = msg.findings?.reduce((sum, f) => sum + f.findings.length, 0) || 0;
countNumber.textContent = String(count);
countNumber.classList.toggle('has-findings', count > 0);
countLabel.textContent = count === 1 ? 'anti-pattern' : 'anti-patterns';
btnScan.textContent = 'Scan page';
btnScan.disabled = false;
scanError.hidden = true;
}
if (msg.action === 'scan-failed') {
btnScan.textContent = 'Scan page';
btnScan.disabled = false;
scanError.textContent = msg.message || 'Couldn\u2019t scan this page.';
scanError.hidden = false;
}
if (msg.action === 'overlays-toggled-broadcast') {
overlaysVisible = msg.visible;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
}
});
btnScan.addEventListener('click', async () => {
const tabId = await getActiveTabId();
if (!tabId) return;
activeTabId = tabId;
scanError.hidden = true;
btnScan.textContent = 'Scanning...';
btnScan.disabled = true;
chrome.runtime.sendMessage({ action: 'scan', tabId });
});
btnToggle.addEventListener('click', async () => {
const tabId = await getActiveTabId();
if (!tabId) return;
chrome.runtime.sendMessage({ action: 'toggle-overlays', tabId });
overlaysVisible = !overlaysVisible;
btnToggle.textContent = overlaysVisible ? 'Hide overlays' : 'Show overlays';
});
loadState();