const ANALYZER_URL = 'http://localhost:8088/'; const VOLUMIO_URL = 'http://localhost:3000/'; function matchingTabs(tabs, url) { return tabs.filter(tab => tab.url && tab.url.startsWith(url)); } // Keep one Analyzer and one Volumio tab. Chromium starts on Analyzer, so // Volumio can load in the background without delaying the first visible UI. function ensureDualTabs() { chrome.tabs.query({ currentWindow: true }, tabs => { const analyzerTabs = matchingTabs(tabs, ANALYZER_URL); const volumioTabs = matchingTabs(tabs, VOLUMIO_URL); const duplicates = [...analyzerTabs.slice(1), ...volumioTabs.slice(1)] .map(tab => tab.id) .filter(id => Number.isInteger(id)); if (duplicates.length > 0) chrome.tabs.remove(duplicates); if (analyzerTabs.length === 0) chrome.tabs.create({ url: ANALYZER_URL, active: true }); if (volumioTabs.length === 0) chrome.tabs.create({ url: VOLUMIO_URL, active: false }); }); } // Activate an existing application tab without reloading it. function activateOrCreate(url) { chrome.tabs.query({ currentWindow: true }, tabs => { const tab = matchingTabs(tabs, url)[0]; if (tab) chrome.tabs.update(tab.id, { active: true }); else chrome.tabs.create({ url, active: true }); }); } chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => { if (!msg) return; if (msg.cmd === 'bootstrap') { ensureDualTabs(); sendResponse({ ok: true }); return; } if (msg.cmd === 'toggle') { if (msg.from === 'volumio') activateOrCreate(ANALYZER_URL); else activateOrCreate(VOLUMIO_URL); sendResponse({ ok: true }); } });