summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/images/logo-off.pngbin0 -> 8466 bytes
-rw-r--r--assets/images/logo-off_48.pngbin0 -> 1324 bytes
-rw-r--r--assets/images/logo-off_96.pngbin0 -> 2554 bytes
-rw-r--r--assets/images/logo.pngbin168763 -> 21411 bytes
-rw-r--r--assets/images/logo_48.pngbin4984 -> 3054 bytes
-rw-r--r--assets/images/logo_96.pngbin13741 -> 6333 bytes
-rw-r--r--background.js247
-rw-r--r--data-viewer/data-viewer.html2
-rw-r--r--manifest.json8
-rw-r--r--popup/popup.html2
10 files changed, 255 insertions, 4 deletions
diff --git a/assets/images/logo-off.png b/assets/images/logo-off.png
new file mode 100644
index 0000000..3ee5eda
--- /dev/null
+++ b/assets/images/logo-off.png
Binary files differ
diff --git a/assets/images/logo-off_48.png b/assets/images/logo-off_48.png
new file mode 100644
index 0000000..d502afc
--- /dev/null
+++ b/assets/images/logo-off_48.png
Binary files differ
diff --git a/assets/images/logo-off_96.png b/assets/images/logo-off_96.png
new file mode 100644
index 0000000..095a910
--- /dev/null
+++ b/assets/images/logo-off_96.png
Binary files differ
diff --git a/assets/images/logo.png b/assets/images/logo.png
index 1e56728..ad65e4f 100644
--- a/assets/images/logo.png
+++ b/assets/images/logo.png
Binary files differ
diff --git a/assets/images/logo_48.png b/assets/images/logo_48.png
index d083002..44a945f 100644
--- a/assets/images/logo_48.png
+++ b/assets/images/logo_48.png
Binary files differ
diff --git a/assets/images/logo_96.png b/assets/images/logo_96.png
index 9b402a6..d71f36c 100644
--- a/assets/images/logo_96.png
+++ b/assets/images/logo_96.png
Binary files differ
diff --git a/background.js b/background.js
index 2696887..60fd68e 100644
--- a/background.js
+++ b/background.js
@@ -6,6 +6,18 @@ let logging = true; // Enable logging for debugging
// Create a cache for pre-processed CSS to speed up repeated visits
const cssCache = new Map();
const activeTabs = new Map();
+// Cache for styling state to avoid repeated storage lookups
+const stylingStateCache = new Map();
+
+// Icon states for the browser action
+const ICON_ON = {
+ 48: "assets/images/logo_48.png",
+ 96: "assets/images/logo_96.png",
+};
+const ICON_OFF = {
+ 48: "assets/images/logo-off_48.png",
+ 96: "assets/images/logo-off_96.png",
+};
// Default settings to use when values are missing
const DEFAULT_SETTINGS = {
@@ -36,6 +48,181 @@ function ensureDefaultSettings(settings = {}) {
return result;
}
+// Determine if styling should be applied to a hostname
+// This is the centralized logic for both CSS application and icon updates
+async function shouldApplyStyling(hostname) {
+ try {
+ // Check if we already have the answer cached
+ const cacheKey = `styling:${hostname}`;
+ if (stylingStateCache.has(cacheKey)) {
+ return stylingStateCache.get(cacheKey);
+ }
+
+ const normalizedHostname = normalizeHostname(hostname);
+
+ // Get global settings - this is an unavoidable storage lookup
+ const settingsData = await browser.storage.local.get(BROWSER_STORAGE_KEY);
+ const settings = ensureDefaultSettings(
+ settingsData[BROWSER_STORAGE_KEY] || {}
+ );
+
+ // If styling is globally disabled, styling is disabled
+ if (!settings.enableStyling) {
+ stylingStateCache.set(cacheKey, false);
+ return false;
+ }
+
+ // Check if we have a specific style for this site
+ let hasSpecificStyle = false;
+
+ // Check for exact match first
+ if (
+ cssCache.has(normalizedHostname) ||
+ cssCache.has(`www.${normalizedHostname}`)
+ ) {
+ hasSpecificStyle = true;
+ } else {
+ // Check for wildcard and TLD matches
+ for (const cachedSite of cssCache.keys()) {
+ // Wildcard match
+ if (cachedSite.startsWith("+")) {
+ const baseSite = cachedSite.slice(1);
+ if (
+ normalizedHostname === baseSite ||
+ normalizedHostname.endsWith(`.${baseSite}`)
+ ) {
+ hasSpecificStyle = true;
+ break;
+ }
+ }
+ // TLD suffix match
+ else if (cachedSite.startsWith("-")) {
+ const baseSite = cachedSite.slice(1);
+ const cachedDomain = baseSite.split(".").slice(0, -1).join(".");
+ const hostParts = normalizedHostname.split(".");
+ const hostDomain =
+ hostParts.length > 1
+ ? hostParts.slice(0, -1).join(".")
+ : normalizedHostname;
+
+ if (cachedDomain && hostDomain && hostDomain === cachedDomain) {
+ hasSpecificStyle = true;
+ break;
+ }
+ }
+ // Subdomain match
+ else if (
+ normalizedHostname !== cachedSite &&
+ normalizedHostname.endsWith(`.${cachedSite}`) &&
+ !cachedSite.startsWith("-")
+ ) {
+ hasSpecificStyle = true;
+ break;
+ }
+ }
+ }
+
+ // If we have a specific style, check blacklist/whitelist for regular styling
+ if (hasSpecificStyle) {
+ // Get skip styling list - only do this lookup if we have a specific style
+ const skipStyleListData = await browser.storage.local.get(
+ SKIP_THEMING_KEY
+ );
+ const skipStyleList = skipStyleListData[SKIP_THEMING_KEY] || [];
+
+ // In whitelist mode: only apply if site is in the list
+ // In blacklist mode: apply unless site is in the list
+ const styleMode = settings.whitelistStyleMode || false;
+
+ if (styleMode) {
+ // Whitelist mode
+ const shouldApply = skipStyleList.includes(normalizedHostname);
+ stylingStateCache.set(cacheKey, shouldApply);
+ return shouldApply;
+ } else {
+ // Blacklist mode
+ const shouldApply = !skipStyleList.includes(normalizedHostname);
+ stylingStateCache.set(cacheKey, shouldApply);
+ return shouldApply;
+ }
+ }
+
+ // If no specific style, check if we should apply forced styling
+ if (settings.forceStyling) {
+ // Get skip force list - only do this lookup if force styling is enabled
+ const skipForceListData = await browser.storage.local.get(
+ SKIP_FORCE_THEMING_KEY
+ );
+ const skipForceList = skipForceListData[SKIP_FORCE_THEMING_KEY] || [];
+ const isWhitelistMode = settings.whitelistMode || false;
+
+ // In whitelist mode: only apply if site is in the list
+ // In blacklist mode: apply unless site is in the list
+ if (isWhitelistMode) {
+ const shouldApply = skipForceList.includes(normalizedHostname);
+ stylingStateCache.set(cacheKey, shouldApply);
+ return shouldApply;
+ } else {
+ const shouldApply = !skipForceList.includes(normalizedHostname);
+ stylingStateCache.set(cacheKey, shouldApply);
+ return shouldApply;
+ }
+ }
+
+ // No styling applies
+ stylingStateCache.set(cacheKey, false);
+ return false;
+ } catch (error) {
+ console.error("Error determining styling state:", error);
+ return false;
+ }
+}
+
+// Update the icon based on whether styling is active for the current tab
+async function updateIconForTab(tabId, url) {
+ try {
+ if (!url) {
+ const tab = await browser.tabs.get(tabId);
+ url = tab.url;
+ }
+
+ // Non-HTTP URLs don't get styling
+ if (!url || !url.startsWith("http")) {
+ setIcon(tabId, false);
+ return;
+ }
+
+ const urlObj = new URL(url);
+ const hostname = urlObj.hostname;
+
+ // Determine if we should apply styling using the centralized logic
+ const isStylingEnabled = await shouldApplyStyling(hostname);
+
+ // Update the icon based on whether styling is enabled for this site
+ setIcon(tabId, isStylingEnabled);
+
+ if (logging)
+ console.log(
+ `Icon updated for ${hostname}: styling ${
+ isStylingEnabled ? "ON" : "OFF"
+ }`
+ );
+ } catch (error) {
+ console.error("Error updating icon:", error);
+ // Default to off icon in case of error
+ setIcon(tabId, false);
+ }
+}
+
+// Set the icon to either on or off state
+function setIcon(tabId, isEnabled) {
+ const iconSet = isEnabled ? ICON_ON : ICON_OFF;
+ browser.browserAction.setIcon({
+ path: iconSet,
+ tabId: tabId,
+ });
+}
+
// Preload styles for faster injection
async function preloadStyles() {
try {
@@ -89,6 +276,9 @@ browser.webNavigation.onBeforeNavigate.addListener((details) => {
const url = new URL(details.url);
const normalizedHostname = normalizeHostname(url.hostname);
prepareStylesForUrl(normalizedHostname, details.tabId);
+
+ // Update icon for this tab
+ updateIconForTab(details.tabId, details.url);
}
});
@@ -131,6 +321,11 @@ browser.runtime.onMessage.addListener(async (message, sender) => {
return true;
}
+ // Update the icon when the content script reports ready
+ if (message.action === "contentScriptReady" && sender.tab) {
+ updateIconForTab(sender.tab.id, sender.tab.url);
+ }
+
return false;
});
@@ -303,6 +498,12 @@ async function applyCSSToTab(tab) {
(styleMode && !skipStyleList.includes(hostname))
) {
console.log("DEBUG: Styling is disabled, exiting early");
+ // Make sure the icon is updated to reflect the disabled state
+ setIcon(tab.id, false);
+
+ // Clear the cache entry to ensure we don't have stale data
+ const cacheKey = `styling:${hostname}`;
+ stylingStateCache.set(cacheKey, false);
return;
}
@@ -465,8 +666,16 @@ async function applyCSSToTab(tab) {
} else {
console.log("DEBUG: Force styling is disabled, no styles applied");
}
+
+ // After successfully applying CSS, update the icon to ON state
+ // and update the styling state cache
+ const cacheKey = `styling:${hostname}`;
+ stylingStateCache.set(cacheKey, true);
+ setIcon(tab.id, true);
} catch (error) {
console.error(`DEBUG ERROR: Error applying CSS:`, error);
+ // If there's an error, make sure the icon is OFF
+ setIcon(tab.id, false);
}
}
@@ -559,8 +768,40 @@ async function applyCSS(tabId, hostname, features) {
} else {
console.log(`DEBUG: No CSS to inject after filtering features`);
}
+
+ // Update the icon based on our current state
+ setIcon(tabId, stylingStateCache.get(`styling:${hostname}`) || false);
}
+// Also update icons when tabs are updated
+browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
+ if (changeInfo.status === "complete") {
+ updateIconForTab(tabId, tab.url);
+ }
+});
+
+// Update the icon when a tab becomes active
+browser.tabs.onActivated.addListener((activeInfo) => {
+ updateIconForTab(activeInfo.tabId);
+});
+
+// Clear cache on settings changes
+browser.storage.onChanged.addListener((changes, areaName) => {
+ if (areaName === "local") {
+ if (
+ changes[BROWSER_STORAGE_KEY] ||
+ changes[SKIP_THEMING_KEY] ||
+ changes[SKIP_FORCE_THEMING_KEY]
+ ) {
+ // Clear the styling state cache when relevant settings change
+ stylingStateCache.clear();
+
+ if (logging)
+ console.log("Cleared styling state cache due to settings change");
+ }
+ }
+});
+
let autoUpdateInterval;
function startAutoUpdate() {
@@ -653,6 +894,12 @@ async function initializeExtension() {
if (validatedSettings.autoUpdate) {
startAutoUpdate();
}
+
+ // Update icons for all tabs on extension startup
+ const tabs = await browser.tabs.query({});
+ for (const tab of tabs) {
+ updateIconForTab(tab.id, tab.url);
+ }
}
// Listen for specific navigation events to apply CSS as early as possible
diff --git a/data-viewer/data-viewer.html b/data-viewer/data-viewer.html
index b0d4a5f..716942d 100644
--- a/data-viewer/data-viewer.html
+++ b/data-viewer/data-viewer.html
@@ -16,7 +16,7 @@
<header class="app-header">
<div id="header-container">
<div class="logo-container">
- <img src="../assets/images/logo_48.png" alt="ZenInternet Logo" class="logo-img">
+ <img src="../assets/images/logo.png" alt="ZenInternet Logo" class="logo-img">
<h1 class="app-title">Zen Internet Settings</h1>
</div>
<div class="miniheader">
diff --git a/manifest.json b/manifest.json
index aeb6de8..320eb23 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Zen Internet",
- "version": "1.9.2",
+ "version": "2.0.0",
"description": "Make the internet feel native and elegant. Zen Internet is a browser extension that enhances your browsing experience by providing a clean and minimalistic interface with transparency and a focus on content. Customize the features in the addon popup.",
"browser_specific_settings": {
"gecko": {
@@ -23,7 +23,11 @@
],
"browser_action": {
"default_popup": "popup/popup.html",
- "default_title": "Zen Internet"
+ "default_title": "Zen Internet",
+ "default_icon": {
+ "48": "assets/images/logo_48.png",
+ "96": "assets/images/logo_96.png"
+ }
},
"background": {
"scripts": ["background.js"],
diff --git a/popup/popup.html b/popup/popup.html
index bc5b92b..ae497bc 100644
--- a/popup/popup.html
+++ b/popup/popup.html
@@ -14,7 +14,7 @@
<header class="app-header">
<div id="header-container">
<div class="logo-container">
- <img src="../assets/images/logo_48.png" alt="ZenInternet Logo" class="logo-img">
+ <img src="../assets/images/logo.png" alt="ZenInternet Logo" class="logo-img">
<h1 class="app-title">Zen Internet</h1>
</div>
<div class="miniheader">