diff options
author | sameerasw <[email protected]> | 2025-04-10 14:27:39 +0530 |
---|---|---|
committer | sameerasw <[email protected]> | 2025-04-10 14:27:42 +0530 |
commit | 7f45e1729c777de8f37e2f98bd58957a13d7027b (patch) | |
tree | 4d7dd2d6e58fd84fe55d28e72cdf0712938885a9 /popup | |
parent | 01226d8f74a1353d075fe4816fe167375ea8e178 (diff) |
Added whitelist and blacklist toggle for forcing themes
Diffstat (limited to 'popup')
-rw-r--r-- | popup/popup.css | 51 | ||||
-rw-r--r-- | popup/popup.html | 9 | ||||
-rw-r--r-- | popup/popup.js | 141 |
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"; + } + } })(); |