mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 14:16:28 +03:00
* 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>
85 lines
3.1 KiB
JavaScript
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();
|