Skip to content

Instantly share code, notes, and snippets.

@yokeshrana
Created May 20, 2026 19:42
Show Gist options
  • Select an option

  • Save yokeshrana/f8cb5622a415771e57558618a6c42f8c to your computer and use it in GitHub Desktop.

Select an option

Save yokeshrana/f8cb5622a415771e57558618a6c42f8c to your computer and use it in GitHub Desktop.
dark mode safari
/**
* 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