Created
May 20, 2026 19:42
-
-
Save yokeshrana/f8cb5622a415771e57558618a6c42f8c to your computer and use it in GitHub Desktop.
dark mode safari
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * background.js — Smart Dark Mode Extension | |
| * | |
| * Responsibilities: | |
| * - Icon state management | |
| * - Forwarding toggle messages to active tab | |
| * - Re-injecting content script into existing tabs on install/update | |
| * - Responding to tab URL changes (re-trigger smart detection per page) | |
| */ | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // ICON UPDATE | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| function updateIcon(enabled, tabId) { | |
| const folder = enabled ? 'enabled' : 'disabled'; | |
| const iconSpec = { | |
| path: { | |
| "16": `icons/${folder}/icon16.png`, | |
| "48": `icons/${folder}/icon48.png`, | |
| "128": `icons/${folder}/icon128.png`, | |
| } | |
| }; | |
| if (tabId) iconSpec.tabId = tabId; | |
| chrome.action.setIcon(iconSpec); | |
| } | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // INSTALL / UPDATE — inject into all existing tabs so reload isn't required | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| chrome.runtime.onInstalled.addListener(async (details) => { | |
| // Set defaults only on fresh install (not on update, to preserve user prefs) | |
| if (details.reason === 'install') { | |
| await chrome.storage.local.set({ enabled: true, smartDetection: true }); | |
| } | |
| // Re-inject content script into all open, scriptable tabs | |
| const tabs = await chrome.tabs.query({}); | |
| for (const tab of tabs) { | |
| if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://')) continue; | |
| try { | |
| await chrome.scripting.executeScript({ | |
| target: { tabId: tab.id }, | |
| files: ['content.js'], | |
| }); | |
| } catch (_) { | |
| // Tab may not allow script injection (e.g. PDF, devtools) — silently skip | |
| } | |
| } | |
| // Sync icon with current state | |
| const result = await chrome.storage.local.get(['enabled']); | |
| updateIcon(result.enabled !== false); | |
| }); | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // STARTUP — sync icon | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| chrome.runtime.onStartup.addListener(async () => { | |
| const result = await chrome.storage.local.get(['enabled']); | |
| updateIcon(result.enabled !== false); | |
| }); | |
| // Also sync immediately at service-worker boot | |
| chrome.storage.local.get(['enabled'], (result) => { | |
| updateIcon(result.enabled !== false); | |
| }); | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // MESSAGES FROM POPUP | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | |
| // Popup asking to update the icon | |
| if (message.action === 'updateIcon') { | |
| updateIcon(message.enabled, message.tabId || null); | |
| sendResponse({ ok: true }); | |
| return true; | |
| } | |
| // Popup toggled the switch — forward to the active tab's content script | |
| if (message.action === 'toggle' || message.action === 'refresh' || | |
| message.action === 'enable' || message.action === 'disable') { | |
| chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { | |
| if (tabs[0]) { | |
| chrome.tabs.sendMessage(tabs[0].id, message, () => { | |
| // Suppress "no receiving end" errors for pages without content script | |
| if (chrome.runtime.lastError) {} | |
| }); | |
| } | |
| }); | |
| sendResponse({ ok: true }); | |
| return true; | |
| } | |
| // Popup asking for current state | |
| if (message.action === 'getState') { | |
| chrome.storage.local.get(['enabled', 'smartDetection'], (result) => { | |
| sendResponse({ | |
| enabled: result.enabled !== false, | |
| smartDetection: result.smartDetection !== false, | |
| }); | |
| }); | |
| return true; // keep channel open for async sendResponse | |
| } | |
| }); | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // TAB EVENTS — re-trigger content script on navigation (SPA & full loads) | |
| // ───────────────────────────────────────────────────────────────────────────── | |
| // When a tab finishes loading, tell its content script to re-evaluate | |
| chrome.tabs.onUpdated.addListener((tabId, changeInfo) => { | |
| if (changeInfo.status !== 'complete') return; | |
| chrome.storage.local.get(['enabled'], (result) => { | |
| if (result.enabled === false) return; | |
| chrome.tabs.sendMessage(tabId, { action: 'refresh' }, () => { | |
| if (chrome.runtime.lastError) {} // content script not injected yet — fine | |
| }); | |
| }); | |
| }); | |
| // Keep icon in sync when user switches tabs | |
| chrome.tabs.onActivated.addListener(async ({ tabId }) => { | |
| const result = await chrome.storage.local.get(['enabled']); | |
| updateIcon(result.enabled !== false, tabId); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment