summaryrefslogtreecommitdiff
path: root/popup
diff options
context:
space:
mode:
authorsameerasw <[email protected]>2025-04-10 14:27:39 +0530
committersameerasw <[email protected]>2025-04-10 14:27:42 +0530
commit7f45e1729c777de8f37e2f98bd58957a13d7027b (patch)
tree4d7dd2d6e58fd84fe55d28e72cdf0712938885a9 /popup
parent01226d8f74a1353d075fe4816fe167375ea8e178 (diff)
Added whitelist and blacklist toggle for forcing themes
Diffstat (limited to 'popup')
-rw-r--r--popup/popup.css51
-rw-r--r--popup/popup.html9
-rw-r--r--popup/popup.js141
3 files changed, 169 insertions, 32 deletions
diff --git a/popup/popup.css b/popup/popup.css
index 0058174..1a47b2a 100644
--- a/popup/popup.css
+++ b/popup/popup.css
@@ -1,4 +1,4 @@
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
+@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap");
:root {
--radius-sm: 6px;
@@ -7,7 +7,7 @@
--transition: all 0.2s ease;
--shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
--accent-color: #f98764; /* Subtle Zen-themed orange */
- --hover-color: #fa9475; /* Lighter hover state */
+ --hover-color: #fa9475; /* Lighter hover state */
--success-color: #40c057;
--warning-color: #fab005;
--danger-color: #fa5252;
@@ -22,7 +22,7 @@ body {
width: 360px;
margin: 0;
padding: 0;
- font-family: 'Inter', Arial, sans-serif;
+ font-family: "Inter", Arial, sans-serif;
color: var(--text-primary);
background-color: var(--bg-color);
font-size: 14px;
@@ -106,8 +106,14 @@ body {
}
@keyframes fadeIn {
- from { opacity: 0; transform: translateY(-5px); }
- to { opacity: 1; transform: translateY(0); }
+ from {
+ opacity: 0;
+ transform: translateY(-5px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.toggle-switch {
@@ -243,7 +249,7 @@ input:checked + .slider:before {
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
background-color: var(--bg-color);
-
+
/* Firefox scrollbar styling */
scrollbar-width: thin;
scrollbar-color: var(--accent-color) transparent;
@@ -355,6 +361,14 @@ input:checked + .slider:before {
padding-left: 9px !important; /* Compensate for the border */
}
+/* Mode Indicator */
+.mode-indicator {
+ font-size: 0.85em;
+ color: var(--text-secondary);
+ margin: 8px 0;
+ font-style: italic;
+}
+
.current-badge {
display: inline-block;
background-color: var(--accent-color);
@@ -387,8 +401,12 @@ input:checked + .slider:before {
}
@keyframes fadeIn {
- from { opacity: 0.7; }
- to { opacity: 1; }
+ from {
+ opacity: 0.7;
+ }
+ to {
+ opacity: 1;
+ }
}
/* Make sure the text doesn't overflow */
@@ -404,22 +422,29 @@ input:checked + .slider:before {
margin-right: 4px;
}
-#addon-version, #last-fetched-time{
+#addon-version,
+#last-fetched-time {
font-size: 0.75em;
}
-.forcing-container{
+.forcing-container {
background-color: var(--secondary-bg);
border-radius: var(--radius-md);
padding: 16px;
margin-bottom: 16px;
}
-.warning{
+.warning {
color: var(--warning-color);
margin-top: 8px;
}
-#reload{
+#reload {
margin-top: 16px;
-} \ No newline at end of file
+}
+
+.mode-hint {
+ font-size: 0.75em;
+ color: var(--text-secondary);
+ margin-left: 8px;
+}
diff --git a/popup/popup.html b/popup/popup.html
index c07e5fa..8ffa03d 100644
--- a/popup/popup.html
+++ b/popup/popup.html
@@ -73,10 +73,17 @@
</div>
<div class="toggle-container">
<label class="toggle-switch">
+ <input type="checkbox" id="whitelist-mode">
+ <span class="slider round"></span>
+ </label>
+ <span id="whitelist-mode-label" class="toggle-label">Blacklist Mode</span>
+ </div>
+ <div class="toggle-container">
+ <label class="toggle-switch">
<input type="checkbox" id="skip-force-theming">
<span class="slider round"></span>
</label>
- <span class="toggle-label">Skip Forcing for this Site</span>
+ <span id="site-toggle-label" class="toggle-label">Skip Forcing for this Site</span>
</div>
</div>
diff --git a/popup/popup.js b/popup/popup.js
index a71eb4f..d81ed7d 100644
--- a/popup/popup.js
+++ b/popup/popup.js
@@ -13,9 +13,13 @@ new (class ExtensionPopup {
autoUpdateSwitch = document.getElementById("auto-update");
lastFetchedTime = document.getElementById("last-fetched-time");
forceStylingSwitch = document.getElementById("force-styling");
+ whitelistModeSwitch = document.getElementById("whitelist-mode");
+ whitelistModeLabel = document.getElementById("whitelist-mode-label");
skipForceThemingSwitch = document.getElementById("skip-force-theming");
+ siteToggleLabel = document.getElementById("site-toggle-label");
skipForceThemingList = [];
reloadButton = document.getElementById("reload");
+ modeIndicator = document.getElementById("mode-indicator");
constructor() {
if (logging) console.log("Initializing ExtensionPopup");
@@ -45,6 +49,11 @@ new (class ExtensionPopup {
);
this.reloadButton.addEventListener("click", this.reloadPage.bind(this));
+ this.whitelistModeSwitch.addEventListener(
+ "change",
+ this.handleWhitelistModeChange.bind(this)
+ );
+
// Setup auto-update and display last fetched time
this.setupAutoUpdate();
this.displayLastFetchedTime();
@@ -97,9 +106,18 @@ new (class ExtensionPopup {
this.globalSettings.enableStyling ?? true;
this.autoUpdateSwitch.checked = this.globalSettings.autoUpdate ?? false;
this.forceStylingSwitch.checked = this.globalSettings.forceStyling ?? false;
- this.skipForceThemingSwitch.checked = this.skipForceThemingList.includes(
+ this.whitelistModeSwitch.checked =
+ this.globalSettings.whitelistMode ?? false;
+
+ this.updateModeLabels();
+
+ // In whitelist mode, checked means "include this site"
+ // In blacklist mode, checked means "skip this site"
+ const isInList = this.skipForceThemingList.includes(
this.currentSiteHostname
);
+ this.skipForceThemingSwitch.checked = isInList;
+
this.loadCurrentSiteFeatures();
}
@@ -131,6 +149,7 @@ new (class ExtensionPopup {
this.globalSettings.enableStyling = this.enableStylingSwitch.checked;
this.globalSettings.autoUpdate = this.autoUpdateSwitch.checked;
this.globalSettings.forceStyling = this.forceStylingSwitch.checked;
+ this.globalSettings.whitelistMode = this.whitelistModeSwitch.checked;
browser.storage.local
.set({
@@ -180,14 +199,20 @@ new (class ExtensionPopup {
const index = this.skipForceThemingList.indexOf(this.currentSiteHostname);
if (isChecked && index === -1) {
+ // Add to the list (whitelist: include, blacklist: skip)
this.skipForceThemingList.push(this.currentSiteHostname);
} else if (!isChecked && index !== -1) {
+ // Remove from the list (whitelist: exclude, blacklist: include)
this.skipForceThemingList.splice(index, 1);
}
- browser.storage.local.set({
- [SKIP_FORCE_THEMING_KEY]: this.skipForceThemingList,
- });
+ browser.storage.local
+ .set({
+ [SKIP_FORCE_THEMING_KEY]: this.skipForceThemingList,
+ })
+ .then(() => {
+ this.updateActiveTabStyling();
+ });
}
async loadCurrentSiteFeatures() {
@@ -335,34 +360,51 @@ new (class ExtensionPopup {
const hostname = url.hostname;
try {
- await browser.tabs.removeCSS(tab.id, {
- code: "/* Placeholder for removing CSS */",
- });
- } catch (error) {}
+ // Try to remove any existing CSS first
+ try {
+ await browser.tabs.removeCSS(tab.id, {
+ code: "/* Placeholder for removing CSS */",
+ });
+ } catch (error) {
+ // Ignore errors as they may occur if no CSS was previously applied
+ }
- if (!this.shouldApplyCSS(hostname)) return;
+ if (!this.shouldApplyCSS(hostname)) return;
- try {
const stylesData = await browser.storage.local.get("styles");
const styles = stylesData.styles?.website || {};
- let siteKey = null;
+ // First try to find a direct match for a CSS file
+ let bestMatch = null;
+ let bestMatchLength = 0;
+
for (const site of Object.keys(styles)) {
const siteName = site.replace(/\.css$/, "");
if (siteName.startsWith("+")) {
const baseSiteName = siteName.slice(1);
- if (hostname.endsWith(baseSiteName)) {
- siteKey = site;
- break;
+ if (
+ hostname.endsWith(baseSiteName) &&
+ baseSiteName.length > bestMatchLength
+ ) {
+ bestMatch = site;
+ bestMatchLength = baseSiteName.length;
}
} else if (hostname === siteName || hostname === `www.${siteName}`) {
- siteKey = site;
+ // Exact match has priority
+ bestMatch = site;
break;
+ } else if (
+ hostname.endsWith(siteName) &&
+ siteName.length > bestMatchLength
+ ) {
+ bestMatch = site;
+ bestMatchLength = siteName.length;
}
}
- if (siteKey && styles[siteKey]) {
- const features = styles[siteKey];
+ // If we found a direct match, use it
+ if (bestMatch) {
+ const features = styles[bestMatch];
const siteStorageKey = `${this.BROWSER_STORAGE_KEY}.${hostname}`;
const siteData = await browser.storage.local.get(siteStorageKey);
const featureSettings = siteData[siteStorageKey] || {};
@@ -376,7 +418,36 @@ new (class ExtensionPopup {
if (combinedCSS) {
await browser.tabs.insertCSS(tab.id, { code: combinedCSS });
- console.info(`Applied CSS to ${hostname}`);
+ console.info(`Applied CSS to ${hostname} (direct match)`);
+ }
+ } else if (this.globalSettings.forceStyling) {
+ // Otherwise check for forced styling
+ const isInList = this.skipForceThemingList.includes(hostname);
+ const isWhitelistMode = this.globalSettings.whitelistMode;
+
+ // Determine if we should apply forced styling
+ const shouldApplyForcedStyling =
+ (isWhitelistMode && isInList) || (!isWhitelistMode && !isInList);
+
+ if (shouldApplyForcedStyling && styles["example.com.css"]) {
+ const features = styles["example.com.css"];
+ const siteStorageKey = `${this.BROWSER_STORAGE_KEY}.${hostname}`;
+ const siteData = await browser.storage.local.get(siteStorageKey);
+ const featureSettings = siteData[siteStorageKey] || {};
+
+ let combinedCSS = "";
+ for (const [feature, css] of Object.entries(features)) {
+ if (featureSettings[feature] !== false) {
+ combinedCSS += css + "\n";
+ }
+ }
+
+ if (combinedCSS) {
+ await browser.tabs.insertCSS(tab.id, { code: combinedCSS });
+ console.info(`Applied forced CSS to ${hostname}`);
+ }
+ } else {
+ console.info(`Skipping forced styling for ${hostname}`);
}
}
} catch (error) {
@@ -434,4 +505,38 @@ new (class ExtensionPopup {
}
}
}
+
+ handleWhitelistModeChange() {
+ this.updateModeLabels();
+ this.saveSettings();
+ }
+
+ updateModeIndicator() {
+ if (this.whitelistModeSwitch.checked) {
+ this.modeIndicator.textContent =
+ "In Whitelist Mode (apply only to listed sites)";
+ } else {
+ this.modeIndicator.textContent =
+ "In Blacklist Mode (apply to all except listed sites)";
+ }
+ }
+
+ updateSiteToggleLabel() {
+ // Update the label based on the current mode
+ if (this.whitelistModeSwitch.checked) {
+ this.siteToggleLabel.textContent = "Enable for this Site";
+ } else {
+ this.siteToggleLabel.textContent = "Skip Forcing for this Site";
+ }
+ }
+
+ updateModeLabels() {
+ if (this.whitelistModeSwitch.checked) {
+ this.whitelistModeLabel.textContent = "Whitelist Mode";
+ this.siteToggleLabel.textContent = "Enable for this Site";
+ } else {
+ this.whitelistModeLabel.textContent = "Blacklist Mode";
+ this.siteToggleLabel.textContent = "Skip Forcing for this Site";
+ }
+ }
})();