diff options
author | sameerasw <[email protected]> | 2025-02-26 11:21:58 +0530 |
---|---|---|
committer | sameerasw <[email protected]> | 2025-02-26 11:22:59 +0530 |
commit | 93747ebef68299c4442df4f907ea836c6e078e57 (patch) | |
tree | 6540db8ad6d11ad9aa7e6d1406c4192d96364909 | |
parent | 02c13d747c626903a2a6b45b2d62e706506b4b6f (diff) |
Featrue specific toggles for styles and new json format
-rw-r--r-- | inject-css.js | 30 | ||||
-rw-r--r-- | popup/popup.css | 59 | ||||
-rw-r--r-- | popup/popup.html | 14 | ||||
-rw-r--r-- | popup/popup.js | 201 | ||||
-rw-r--r-- | sample-styles-old.json | 0 | ||||
-rw-r--r-- | sample-styles.json | 0 |
6 files changed, 176 insertions, 128 deletions
diff --git a/inject-css.js b/inject-css.js index 6b3aaf8..b7c89fe 100644 --- a/inject-css.js +++ b/inject-css.js @@ -2,19 +2,27 @@ browser.storage.local.get("transparentZenSettings").then((settings) => { if (settings.transparentZenSettings?.enableStyling) { browser.storage.local.get("styles").then((data) => { const currentUrl = window.location.hostname; - const cssFileName = Object.keys(data.styles).find((key) => + const cssFileName = Object.keys(data.styles?.website || {}).find((key) => currentUrl.includes(key.replace(".css", "")) ); - if ( - cssFileName && - settings.transparentZenSettings.websiteSettings?.[ - cssFileName.replace(".css", "") - ] !== false - ) { - let style = document.createElement("style"); - style.textContent = data.styles[cssFileName]; - document.head.appendChild(style); - console.log(`Injected custom CSS for ${currentUrl}`); + + if (cssFileName) { + const features = data.styles.website[cssFileName]; + const featureSettings = settings.transparentZenSettings.featureSettings?.[cssFileName] || {}; + + let combinedCSS = ""; + for (const [feature, css] of Object.entries(features)) { + if (featureSettings[feature] !== false) { + combinedCSS += css + "\n"; + } + } + + if (combinedCSS) { + let style = document.createElement("style"); + style.textContent = combinedCSS; + document.head.appendChild(style); + console.log(`Injected custom CSS for ${currentUrl}`); + } } }); } diff --git a/popup/popup.css b/popup/popup.css index 80d3ec1..a0bf264 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -171,13 +171,70 @@ input:checked + .slider:before { margin: 0 0 12px 0;
color: var(--text-primary);
}
+.features-container {
+ background-color: var(--secondary-bg);
+ border-radius: var(--radius-md);
+ padding: 16px;
+ margin-bottom: 16px;
+}
+
+.features-list {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.feature-toggle {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 8px 12px;
+ background-color: var(--bg-color);
+ border-radius: var(--radius-sm);
+ border: 1px solid var(--border-color);
+}
+
+.feature-name {
+ font-weight: 500;
+ color: var(--text-primary);
+}
+/* Collapsible Websites List */
.websites-container {
background-color: var(--secondary-bg);
border-radius: var(--radius-md);
- padding: 16px;
+ overflow: hidden;
}
+.collapsible-button {
+ width: 100%;
+ padding: 12px 16px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: none;
+ border: none;
+ color: var(--text-primary);
+ font-weight: 600;
+ cursor: pointer;
+ transition: var(--transition);
+}
+
+.collapsible-button:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+}
+
+.collapsible-button i {
+ transition: transform 0.3s ease;
+}
+
+.websites-list.collapsed {
+ display: none;
+}
+
+.websites-list:not(.collapsed) + .collapsible-button i {
+ transform: rotate(180deg);
+}
.websites-list {
list-style: none;
padding: 0;
diff --git a/popup/popup.html b/popup/popup.html index 8ccdbd4..657a1a7 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -27,9 +27,19 @@ <span class="toggle-label">Enable Styling</span> </div> + <!-- Current Site Features Section --> + <div id="current-site-features" class="features-container"> + <h2 class="section-title">Current Site Features</h2> + <div id="current-site-toggles" class="features-list"></div> + </div> + + <!-- All Websites Section (Collapsible) --> <div class="websites-container"> - <h2 class="section-title">Available Websites</h2> - <ul id="websites-list" class="websites-list"></ul> + <button class="collapsible-button" id="toggle-websites"> + <span>All Websites</span> + <i class="fas fa-chevron-down"></i> + </button> + <div id="websites-list" class="websites-list collapsed"></div> </div> <div class="actions"> diff --git a/popup/popup.js b/popup/popup.js index dc4b203..161634d 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -4,6 +4,7 @@ new(class ExtensionPopup { enableStylingSwitch = document.getElementById("enable-styling"); refetchCSSButton = document.getElementById("refetch-css"); websitesList = document.getElementById("websites-list"); + currentSiteFeatures = document.getElementById("current-site-toggles"); currentSiteHostname = ""; constructor() { @@ -17,6 +18,9 @@ new(class ExtensionPopup { } }); this.refetchCSSButton.addEventListener("click", this.refetchCSS.bind(this)); + document.getElementById("toggle-websites").addEventListener("click", () => { + this.websitesList.classList.toggle("collapsed"); + }); this.setupContentScriptInjection(); } @@ -40,10 +44,9 @@ new(class ExtensionPopup { this.updateActiveTabStyling(); }); - this.websitesList.addEventListener("change", (event) => { - this.saveSettings(); - // Update styling immediately when a checkbox changes + this.currentSiteFeatures.addEventListener("change", (event) => { if (event.target.type === 'checkbox') { + this.saveSettings(); this.updateActiveTabStyling(); } }); @@ -51,9 +54,9 @@ new(class ExtensionPopup { restoreSettings() { if (this.browserStorageSettings.enableStyling !== undefined) { - this.enableStylingSwitch.checked = - this.browserStorageSettings.enableStyling; + this.enableStylingSwitch.checked = this.browserStorageSettings.enableStyling; } + this.loadCurrentSiteFeatures(); this.loadWebsitesList(); } @@ -64,17 +67,20 @@ new(class ExtensionPopup { } saveSettings() { - this.browserStorageSettings.enableStyling = - this.enableStylingSwitch.checked; + this.browserStorageSettings.enableStyling = this.enableStylingSwitch.checked; - const websiteSettings = {}; - this.websitesList + const featureSettings = {}; + this.currentSiteFeatures .querySelectorAll("input[type=checkbox]") .forEach((checkbox) => { - websiteSettings[checkbox.name] = checkbox.checked; + const [site, feature] = checkbox.name.split('|'); + if (!featureSettings[site]) { + featureSettings[site] = {}; + } + featureSettings[site][feature] = checkbox.checked; }); - this.browserStorageSettings.websiteSettings = websiteSettings; + this.browserStorageSettings.featureSettings = featureSettings; browser.storage.local.set({ [this.BROWSER_STORAGE_KEY]: this.browserStorageSettings, @@ -83,15 +89,51 @@ new(class ExtensionPopup { console.info("Settings saved", this.browserStorageSettings); } + async loadCurrentSiteFeatures() { + try { + const stylesData = await browser.storage.local.get("styles"); + const styles = stylesData.styles?.website || {}; + + this.currentSiteFeatures.innerHTML = ""; + + const currentSiteKey = Object.keys(styles).find(site => + this.isCurrentSite(site.replace(".css", "")) + ); + + if (!currentSiteKey) { + this.currentSiteFeatures.innerHTML = "<div class='feature-toggle'>No styles available for this site.</div>"; + return; + } + + const features = styles[currentSiteKey]; + for (const [feature, css] of Object.entries(features)) { + const isChecked = this.browserStorageSettings.featureSettings?.[currentSiteKey]?.[feature] ?? true; + + const featureToggle = document.createElement("div"); + featureToggle.className = "feature-toggle"; + featureToggle.innerHTML = ` + <span class="feature-name">${feature}</span> + <label class="toggle-switch"> + <input type="checkbox" name="${currentSiteKey}|${feature}" ${isChecked ? "checked" : ""}> + <span class="slider round"></span> + </label> + `; + + this.currentSiteFeatures.appendChild(featureToggle); + } + } catch (error) { + console.error("Error loading current site features:", error); + this.currentSiteFeatures.innerHTML = "<div class='feature-toggle'>Error loading features.</div>"; + } + } + async loadWebsitesList() { try { - // Get the styles from storage that were fetched using refetchCSS const stylesData = await browser.storage.local.get("styles"); - const styles = stylesData.styles || {}; + const styles = stylesData.styles?.website || {}; this.websitesList.innerHTML = ""; - // Use the keys from styles object const websites = Object.keys(styles); if (websites.length === 0) { @@ -101,49 +143,12 @@ new(class ExtensionPopup { return; } - // Create array to hold all website items - const websiteItems = []; - let currentSiteItem = null; - for (const site of websites) { - // Remove the .css extension if present const displayName = site.replace(/\.css$/, ""); - - const isChecked = - this.browserStorageSettings.websiteSettings?.[displayName] ?? true; - const listItem = document.createElement("li"); - - // Check if this site matches the current site - const isCurrent = this.isCurrentSite(displayName); - if (isCurrent) { - listItem.classList.add("current-site"); - currentSiteItem = listItem; // Store the current site item separately - } - - listItem.innerHTML = ` - <label> - <input type="checkbox" name="${displayName}" ${isChecked ? "checked" : ""}> - ${displayName} - ${isCurrent ? '<span class="current-badge">Current</span>' : ''} - </label> - `; - - // Add to array if not current site - if (!isCurrent) { - websiteItems.push(listItem); - } - } - - // Add current site at the top if it exists - if (currentSiteItem) { - this.websitesList.appendChild(currentSiteItem); + listItem.textContent = displayName; + this.websitesList.appendChild(listItem); } - - // Add all other sites - websiteItems.forEach(item => { - this.websitesList.appendChild(item); - }); } catch (error) { console.error("Error loading websites list:", error); this.websitesList.innerHTML = "<li>Error loading websites list. Please try refetching styles.</li>"; @@ -152,21 +157,19 @@ new(class ExtensionPopup { isCurrentSite(siteName) { if (!this.currentSiteHostname) return false; - - // Direct match if (this.currentSiteHostname === siteName) return true; - if (this.currentSiteHostname.startsWith("www.")) { const nonWww = this.currentSiteHostname.replace("www.", ""); if (nonWww === siteName) return true; } + return false; } async refetchCSS() { this.refetchCSSButton.textContent = "Fetching..."; try { const response = await fetch( - "https://sameerasw.github.io/my-internet/styles.json", + "https://github.com/sameerasw/my-internet/raw/refs/heads/experimental/styles.json", { headers: { "Cache-Control": "no-cache", @@ -177,17 +180,15 @@ new(class ExtensionPopup { const styles = await response.json(); await browser.storage.local.set({ styles }); - // Reload the websites list after fetching new styles + this.loadCurrentSiteFeatures(); this.loadWebsitesList(); - - // Update styling on the active tab this.updateActiveTabStyling(); this.refetchCSSButton.textContent = "Done!"; setTimeout(() => { this.refetchCSSButton.textContent = "Refetch latest styles"; }, 2000); - console.info("All styles refetched and updated from GitHub."); + console.info("All styles refetched and updated from GitHub." + styles); } catch (error) { this.refetchCSSButton.textContent = "Error!"; setTimeout(() => { @@ -198,14 +199,11 @@ new(class ExtensionPopup { } setupContentScriptInjection() { - // Listen for tab updates to apply CSS when needed browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (changeInfo.status === 'complete') { this.applyCSSToTab(tab); } }); - - // Also handle tabs that are already open when the extension starts this.updateAllTabs(); } @@ -227,46 +225,42 @@ new(class ExtensionPopup { const url = new URL(tab.url); const hostname = url.hostname; - // First remove any existing CSS try { await browser.tabs.removeCSS(tab.id, { code: "/* Placeholder for removing CSS */" }); - } catch (error) { - // Ignore errors as the tab might not have any CSS injected - } + } catch (error) {} - // Check if we should apply CSS to this site - if (!this.shouldApplyCSS(hostname)) { - return; - } + if (!this.shouldApplyCSS(hostname)) return; try { - // Get the styles from storage const stylesData = await browser.storage.local.get("styles"); - const styles = stylesData.styles || {}; - - // Find matching CSS for this hostname - let cssToApply = null; + const styles = stylesData.styles?.website || {}; - // Check for direct match (with .css extension) - if (styles[hostname + '.css']) { - cssToApply = styles[hostname + '.css']; - } - // Check for domain matches (e.g. youtube.com matches m.youtube.com) - else { - for (const site of Object.keys(styles)) { - const siteName = site.replace(/\.css$/, ""); - if (hostname.includes(siteName)) { - cssToApply = styles[site]; - break; - } + let siteKey = null; + for (const site of Object.keys(styles)) { + const siteName = site.replace(/\.css$/, ""); + if (hostname.includes(siteName)) { + siteKey = site; + break; } } - if (cssToApply) { - await browser.tabs.insertCSS(tab.id, { code: cssToApply }); - console.info(`Applied CSS to ${hostname}`); + if (siteKey && styles[siteKey]) { + const features = styles[siteKey]; + const featureSettings = this.browserStorageSettings.featureSettings?.[siteKey] || {}; + + 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 CSS to ${hostname}`); + } } } catch (error) { console.error(`Error applying CSS to ${hostname}:`, error); @@ -274,27 +268,6 @@ new(class ExtensionPopup { } shouldApplyCSS(hostname) { - // Global enable/disable switch - if (!this.browserStorageSettings.enableStyling) { - return false; - } - - // Check website-specific settings - const websiteSettings = this.browserStorageSettings.websiteSettings || {}; - - // First check for exact hostname match - if (websiteSettings[hostname] !== undefined) { - return websiteSettings[hostname]; - } - - // Then check for domain matches (e.g. youtube.com matches m.youtube.com) - for (const site in websiteSettings) { - if (hostname.includes(site)) { - return websiteSettings[site]; - } - } - - // Default to enabled if no specific setting found - return true; + return this.browserStorageSettings.enableStyling !== false; } })();
\ No newline at end of file diff --git a/sample-styles-old.json b/sample-styles-old.json new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sample-styles-old.json diff --git a/sample-styles.json b/sample-styles.json new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sample-styles.json |