diff options
author | sameerasw <[email protected]> | 2025-04-10 15:09:26 +0530 |
---|---|---|
committer | sameerasw <[email protected]> | 2025-04-10 15:09:26 +0530 |
commit | 6e0a2f92e25b927c559a9b532fe1b087df921e74 (patch) | |
tree | f6f74e13215b56cb9b116cff819a5d19eb54bba1 /data-viewer/data-viewer.js | |
parent | 7f45e1729c777de8f37e2f98bd58957a13d7027b (diff) |
New data viewer page and ability to reset forced sites and all data
Diffstat (limited to 'data-viewer/data-viewer.js')
-rw-r--r-- | data-viewer/data-viewer.js | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/data-viewer/data-viewer.js b/data-viewer/data-viewer.js new file mode 100644 index 0000000..f7a7043 --- /dev/null +++ b/data-viewer/data-viewer.js @@ -0,0 +1,405 @@ +document.addEventListener("DOMContentLoaded", function () { + const BROWSER_STORAGE_KEY = "transparentZenSettings"; + const SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; + + const globalSettingsElement = document.getElementById("global-settings-data"); + const skipListElement = document.getElementById("skip-list-data"); + const combinedWebsitesElement = document.getElementById( + "combined-websites-data" + ); + const backButton = document.getElementById("back-button"); + const refreshButton = document.getElementById("refresh-data"); + const deleteAllButton = document.getElementById("delete-all-data"); + const versionElement = document.getElementById("addon-version"); + + // Load and display the data + loadAllData(); + + // Display addon version + displayAddonVersion(); + + // Event listener for the back button + backButton.addEventListener("click", function () { + window.close(); + }); + + // Event listener for refresh button + refreshButton.addEventListener("click", function () { + loadAllData(); + }); + + // Event listener for delete all data button + deleteAllButton.addEventListener("click", function() { + if (confirm("WARNING: This will delete ALL extension data including settings, website styles, and preferences. This action cannot be undone!\n\nAre you sure you want to proceed?")) { + deleteAllData(); + } + }); + + async function deleteAllData() { + try { + // Clear all storage data + await browser.storage.local.clear(); + + // Show confirmation message + alert("All data has been deleted successfully. The page will now reload."); + + // Reload the page to show empty state + window.location.reload(); + } catch (error) { + console.error("Error deleting data:", error); + alert("An error occurred while trying to delete data: " + error.message); + } + } + + async function displayAddonVersion() { + const manifest = browser.runtime.getManifest(); + versionElement.textContent = `Version: ${manifest.version}`; + } + + async function loadAllData() { + try { + // Load all data from storage + const data = await browser.storage.local.get(null); + + // Display global settings + const globalSettings = data[BROWSER_STORAGE_KEY] || {}; + displayGlobalSettings(globalSettings); + + // Display skip/enable list + const skipList = data[SKIP_FORCE_THEMING_KEY] || []; + displaySkipList(skipList, globalSettings.whitelistMode); + + // Display combined websites and settings + displayCombinedWebsiteData(data); + + console.info("Data loaded successfully"); + } catch (error) { + console.error("Error loading data:", error); + } + } + + function displayGlobalSettings(settings) { + globalSettingsElement.innerHTML = ""; + + const table = document.createElement("table"); + table.classList.add("data-table"); + + // Table header + const thead = document.createElement("thead"); + const headerRow = document.createElement("tr"); + headerRow.innerHTML = `<th>Setting</th><th>Value</th>`; + thead.appendChild(headerRow); + table.appendChild(thead); + + // Table body + const tbody = document.createElement("tbody"); + + for (const [key, value] of Object.entries(settings)) { + // Skip lastFetchedTime as it will be formatted differently + if (key === "lastFetchedTime") continue; + + const row = document.createElement("tr"); + row.innerHTML = ` + <td>${formatSettingName(key)}</td> + <td>${formatSettingValue(value)}</td> + `; + tbody.appendChild(row); + } + + // Add last fetched time with formatted date if available + if (settings.lastFetchedTime) { + const row = document.createElement("tr"); + row.innerHTML = ` + <td>${formatSettingName("lastFetchedTime")}</td> + <td>${new Date(settings.lastFetchedTime).toLocaleString()}</td> + `; + tbody.appendChild(row); + } + + table.appendChild(tbody); + globalSettingsElement.appendChild(table); + } + + function displaySkipList(skipList, isWhitelistMode) { + skipListElement.innerHTML = ""; + + const modeType = isWhitelistMode ? "Whitelist" : "Blacklist"; + const actionType = isWhitelistMode ? "Enabled" : "Skipped"; + + const modeInfo = document.createElement("div"); + modeInfo.classList.add("mode-info"); + modeInfo.innerHTML = `<strong>Current Mode:</strong> ${modeType} Mode - ${ + isWhitelistMode + ? "Only apply forced styling to sites in the list" + : "Apply forced styling to all sites except those in the list" + }`; + skipListElement.appendChild(modeInfo); + + // Add Clear List button + if (skipList.length > 0) { + const clearListButton = document.createElement("button"); + clearListButton.classList.add("action-button", "secondary", "clear-list-button"); + clearListButton.innerHTML = '<i class="fas fa-trash"></i> Clear List'; + clearListButton.addEventListener("click", function() { + if (confirm(`Are you sure you want to clear the entire ${modeType} list? This will affect how styling is applied to websites.`)) { + clearSkipList(); + } + }); + skipListElement.appendChild(clearListButton); + } + + if (skipList.length === 0) { + skipListElement.innerHTML += + '<div class="no-data">No websites in the list.</div>'; + return; + } + + const table = document.createElement("table"); + table.classList.add("data-table"); + + // Table header + const thead = document.createElement("thead"); + const headerRow = document.createElement("tr"); + headerRow.innerHTML = `<th>${actionType} Websites</th>`; + thead.appendChild(headerRow); + table.appendChild(thead); + + // Table body + const tbody = document.createElement("tbody"); + + for (const site of skipList) { + const row = document.createElement("tr"); + row.innerHTML = `<td>${site}</td>`; + tbody.appendChild(row); + } + + table.appendChild(tbody); + skipListElement.appendChild(table); + } + + async function clearSkipList() { + try { + await browser.storage.local.remove(SKIP_FORCE_THEMING_KEY); + alert(`${SKIP_FORCE_THEMING_KEY} has been cleared successfully.`); + loadAllData(); // Reload data to reflect changes + } catch (error) { + console.error("Error clearing skip list:", error); + alert("An error occurred while trying to clear the list: " + error.message); + } + } + + function displayCombinedWebsiteData(data) { + combinedWebsitesElement.innerHTML = ""; + + const styles = data.styles || {}; + const websites = styles.website || {}; + const websiteKeys = Object.keys(websites); + + // Find all site-specific settings + const siteSettings = {}; + for (const [key, value] of Object.entries(data)) { + if (key.startsWith(BROWSER_STORAGE_KEY + ".")) { + const siteName = key.substring(BROWSER_STORAGE_KEY.length + 1); + siteSettings[siteName] = value; + } + } + + if (websiteKeys.length === 0) { + combinedWebsitesElement.innerHTML = + '<div class="no-data">No websites found. Try fetching styles first.</div>'; + return; + } + + // Create search filter + const searchContainer = document.createElement("div"); + searchContainer.classList.add("search-container"); + + const searchInput = document.createElement("input"); + searchInput.type = "text"; + searchInput.placeholder = "Search websites..."; + searchInput.classList.add("search-input"); + searchInput.addEventListener("input", function () { + filterWebsites(this.value.toLowerCase()); + }); + + const searchIcon = document.createElement("i"); + searchIcon.className = "fas fa-search search-icon"; + + searchContainer.appendChild(searchIcon); + searchContainer.appendChild(searchInput); + + combinedWebsitesElement.appendChild(searchContainer); + + // Create expand all button + const expandAllButton = document.createElement("button"); + expandAllButton.classList.add( + "action-button", + "secondary", + "view-all-button" + ); + expandAllButton.textContent = "Expand All"; + expandAllButton.addEventListener("click", function () { + const expanded = this.textContent === "Collapse All"; + const panels = document.querySelectorAll(".website-panel"); + + panels.forEach((panel) => { + const header = panel.querySelector(".website-header"); + const content = panel.querySelector(".website-content"); + + if (expanded) { + header.classList.remove("active"); + content.style.maxHeight = null; + + // Also collapse all CSS blocks + content.querySelectorAll(".css-block-header").forEach((cssHeader) => { + cssHeader.classList.remove("active"); + const cssContent = cssHeader.nextElementSibling; + if (cssContent) cssContent.style.maxHeight = null; + }); + } else { + header.classList.add("active"); + content.style.maxHeight = content.scrollHeight + "px"; + } + }); + + this.textContent = expanded ? "Expand All" : "Collapse All"; + }); + + combinedWebsitesElement.appendChild(expandAllButton); + + const websitesContainer = document.createElement("div"); + websitesContainer.classList.add("websites-container"); + combinedWebsitesElement.appendChild(websitesContainer); + + // Sort websites alphabetically + websiteKeys.sort(); + + // Create panels for each website + for (const website of websiteKeys) { + const websitePanel = document.createElement("div"); + websitePanel.classList.add("website-panel"); + websitePanel.dataset.website = website.toLowerCase(); + + const header = document.createElement("div"); + header.classList.add("website-header"); + + // Create website name with feature count + const features = websites[website]; + const featureCount = Object.keys(features).length; + + // Get site settings if available + const siteName = website.replace(".css", ""); + const domainName = siteName.startsWith("+") + ? siteName.slice(1) + : siteName; + const settingsData = + siteSettings[domainName] || siteSettings[`www.${domainName}`] || {}; + + header.innerHTML = ` + <div class="website-header-content"> + <span class="website-name">${website}</span> + <span class="feature-count">${featureCount} features</span> + </div> + `; + + header.addEventListener("click", function () { + this.classList.toggle("active"); + const content = this.nextElementSibling; + if (content.style.maxHeight) { + content.style.maxHeight = null; + } else { + content.style.maxHeight = content.scrollHeight + "px"; + } + }); + + const content = document.createElement("div"); + content.classList.add("website-content"); + + // Create CSS blocks for each feature + for (const [feature, css] of Object.entries(features)) { + const cssBlock = document.createElement("div"); + cssBlock.classList.add("css-block"); + + // Get the feature's enabled status from site settings + const isEnabled = settingsData[feature] !== false; // true by default + + // Create the block header with feature name and status + const cssBlockHeader = document.createElement("div"); + cssBlockHeader.classList.add("css-block-header"); + cssBlockHeader.innerHTML = ` + <span class="feature-name">${feature}</span> + <span class="feature-status ${isEnabled ? "enabled" : "disabled"}">${ + isEnabled ? "Enabled" : "Disabled" + }</span> + `; + + // Make the CSS block header toggleable + cssBlockHeader.addEventListener("click", function (e) { + // Don't expand if clicking on status badge + if (e.target.classList.contains("feature-status")) return; + + this.classList.toggle("active"); + const cssContent = this.nextElementSibling; + if (cssContent.style.maxHeight) { + cssContent.style.maxHeight = null; + } else { + cssContent.style.maxHeight = cssContent.scrollHeight + "px"; + } + }); + + // Create the CSS content area + const cssContent = document.createElement("div"); + cssContent.classList.add("css-content"); + + const cssCode = document.createElement("pre"); + cssCode.classList.add("css-code"); + cssCode.textContent = css; + cssContent.appendChild(cssCode); + + cssBlock.appendChild(cssBlockHeader); + cssBlock.appendChild(cssContent); + content.appendChild(cssBlock); + } + + websitePanel.appendChild(header); + websitePanel.appendChild(content); + websitesContainer.appendChild(websitePanel); + } + + // Filter function for search + function filterWebsites(query) { + const panels = websitesContainer.querySelectorAll(".website-panel"); + + panels.forEach((panel) => { + const website = panel.dataset.website; + if (website.includes(query)) { + panel.style.display = ""; + } else { + panel.style.display = "none"; + } + }); + } + } + + // Helper Functions + function formatSettingName(name) { + // Convert camelCase to Title Case with spaces + return name + .replace(/([A-Z])/g, " $1") + .replace(/^./, (str) => str.toUpperCase()); + } + + function formatSettingValue(value) { + if (typeof value === "boolean") { + return value + ? '<span class="badge enabled">Enabled</span>' + : '<span class="badge disabled">Disabled</span>'; + } else if (value === null) { + return '<span class="null-value">null</span>'; + } else if (typeof value === "object") { + return '<span class="object-value">{Object}</span>'; + } else { + return value; + } + } +}); |