Skip to content

Commit deb25b7

Browse files
committed
Reactive popup updates via port connection
Previously the popup would show "No Data / No CDN headers found" when opened before page load completed, and had no way to update once open. Changes: - Popup now connects via port and subscribes to updates for the active tab - Background pushes updates when headers or performance metrics arrive - "No Data" message changed to "Navigate or reload to capture headers" which better explains the situation (vs implying no CDN) This replaces polling with event-driven updates: no wasted re-renders, scroll position preserved, and metrics appear as soon as available.
1 parent fe88d0b commit deb25b7

2 files changed

Lines changed: 68 additions & 19 deletions

File tree

CF Cache Status/CF Cache Status Extension/Resources/background.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ const tabData = new Map();
1818
/** Tracks tabs with pending navigations to capture only the first main request */
1919
const pendingNavigations = new Set();
2020

21+
/** Connected popup ports, keyed by tab ID they're watching */
22+
const popupPorts = new Map();
23+
24+
/**
25+
* Notifies the popup if one is connected and watching this tab.
26+
* @param {number} tabId - Tab ID that was updated
27+
*/
28+
function notifyPopup(tabId) {
29+
const port = popupPorts.get(tabId);
30+
if (port) {
31+
port.postMessage({ type: 'update', data: tabData.get(tabId) || null });
32+
}
33+
}
34+
2135
// =============================================================================
2236
// Badge Management
2337
// =============================================================================
@@ -115,6 +129,7 @@ browser.webRequest.onHeadersReceived.addListener(
115129
});
116130

117131
updateBadge(details.tabId, status, cdn);
132+
notifyPopup(details.tabId);
118133
},
119134
{ urls: ['<all_urls>'] },
120135
['responseHeaders']
@@ -175,7 +190,31 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
175190
timestamp: Date.now()
176191
});
177192
}
193+
notifyPopup(sender.tab.id);
178194
}
179195

180196
return true;
181197
});
198+
199+
// Handle popup connections for reactive updates
200+
browser.runtime.onConnect.addListener((port) => {
201+
if (port.name !== 'popup') return;
202+
203+
port.onMessage.addListener((msg) => {
204+
if (msg.type === 'subscribe' && msg.tabId) {
205+
popupPorts.set(msg.tabId, port);
206+
// Send initial data immediately
207+
port.postMessage({ type: 'update', data: tabData.get(msg.tabId) || null });
208+
}
209+
});
210+
211+
port.onDisconnect.addListener(() => {
212+
// Remove port from map when popup closes
213+
for (const [tabId, p] of popupPorts) {
214+
if (p === port) {
215+
popupPorts.delete(tabId);
216+
break;
217+
}
218+
}
219+
});
220+
});

CF Cache Status/CF Cache Status Extension/Resources/popup.js

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,6 @@ const ICONS = {
1212
DASH: '<path d="M7,11h10c0.6,0,1,0.4,1,1s-0.4,1-1,1H7c-0.6,0-1-0.4-1-1S6.4,11,7,11z"/>'
1313
};
1414

15-
// =============================================================================
16-
// Initialization
17-
// =============================================================================
18-
19-
async function init() {
20-
try {
21-
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
22-
if (!tabs?.length) return;
23-
24-
const data = await browser.runtime.sendMessage({ type: 'getTabData', tabId: tabs[0].id });
25-
updateUI(data);
26-
} catch (error) {
27-
console.error('Error loading data:', error);
28-
renderHero('ERROR', 'Error loading data', 'neutral');
29-
}
30-
}
31-
3215
// =============================================================================
3316
// UI Updates
3417
// =============================================================================
@@ -296,5 +279,32 @@ function formatHeaderValue(key, value) {
296279
return value;
297280
}
298281

299-
// Bootstrap
300-
document.addEventListener('DOMContentLoaded', init);
282+
/**
283+
* Bootstrap with reactive updates via port connection.
284+
*
285+
* Instead of polling, the popup subscribes to updates from background.js.
286+
* When data changes (headers received, performance metrics arrive), the
287+
* background pushes the update through the port.
288+
*
289+
* The port auto-disconnects when the popup closes.
290+
*/
291+
document.addEventListener('DOMContentLoaded', async () => {
292+
try {
293+
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
294+
if (!tabs?.length) return;
295+
296+
const port = browser.runtime.connect({ name: 'popup' });
297+
298+
port.onMessage.addListener((msg) => {
299+
if (msg.type === 'update') {
300+
updateUI(msg.data);
301+
}
302+
});
303+
304+
// Subscribe to updates for this tab (also triggers initial data send)
305+
port.postMessage({ type: 'subscribe', tabId: tabs[0].id });
306+
} catch (error) {
307+
console.error('Error connecting:', error);
308+
renderHero('ERROR', 'Error loading data', 'neutral');
309+
}
310+
});

0 commit comments

Comments
 (0)