document.addEventListener("DOMContentLoaded", function () { const BROWSER_STORAGE_KEY = "transparentZenSettings"; const SKIP_FORCE_THEMING_KEY = "skipForceThemingList"; const SKIP_THEMING_KEY = "skipThemingList"; const REPOSITORY_URL_KEY = "stylesRepositoryUrl"; const DEFAULT_REPOSITORY_URL = "https://sameerasw.github.io/my-internet/styles.json"; const globalSettingsElement = document.getElementById("global-settings-data"); const skipListElement = document.getElementById("skip-list-data"); const combinedWebsitesElement = document.getElementById( "combined-websites-data" ); const deleteAllButton = document.getElementById("delete-all-data"); const versionElement = document.getElementById("addon-version"); const disableTransparencyToggle = document.getElementById( "disable-transparency" ); // New toggle elements const disableHoverToggle = document.getElementById("disable-hover"); const disableFooterToggle = document.getElementById("disable-footer"); // Repository URL Elements const repositoryUrlInput = document.getElementById("repository-url"); const setRepositoryUrlButton = document.getElementById("set-repository-url"); const resetRepositoryUrlButton = document.getElementById( "reset-repository-url" ); const repositoryUrlStatus = document.getElementById("repository-url-status"); // Backup & Restore Elements const exportButton = document.getElementById("export-settings"); const importFileInput = document.getElementById("import-file"); const importStatusElement = document.getElementById("import-status"); // Load and display the data loadAllData(); // Display addon version displayAddonVersion(); // Event listener for disable transparency toggle disableTransparencyToggle.addEventListener("change", function () { saveTransparencySettings(this.checked); }); // Event listeners for new toggles disableHoverToggle.addEventListener("change", function () { saveHoverSettings(this.checked); }); disableFooterToggle.addEventListener("change", function () { saveFooterSettings(this.checked); }); // 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(); } }); // Repository URL event listeners setRepositoryUrlButton.addEventListener("click", setRepositoryUrl); resetRepositoryUrlButton.addEventListener("click", resetRepositoryUrl); // New event listeners for export and import functionality exportButton.addEventListener("click", exportSettings); importFileInput.addEventListener("change", importSettings); // Load the repository URL from storage loadRepositoryUrl(); async function loadRepositoryUrl() { try { const data = await browser.storage.local.get(REPOSITORY_URL_KEY); const repositoryUrl = data[REPOSITORY_URL_KEY] || DEFAULT_REPOSITORY_URL; repositoryUrlInput.value = repositoryUrl; } catch (error) { console.error("Error loading repository URL:", error); repositoryUrlInput.value = DEFAULT_REPOSITORY_URL; } } async function setRepositoryUrl() { try { const newUrl = repositoryUrlInput.value.trim(); if (!newUrl) { showRepositoryUrlStatus("Repository URL cannot be empty", "error"); return; } // Simple URL validation try { new URL(newUrl); } catch (e) { showRepositoryUrlStatus("Invalid URL format", "error"); return; } // Save the new URL to storage await browser.storage.local.set({ [REPOSITORY_URL_KEY]: newUrl }); showRepositoryUrlStatus("Repository URL saved successfully", "success"); // Prompt the user to clear styles data if ( confirm( "Would you like to clear existing styles data to avoid conflicts with the new repository?\n\nThis will clear saved styles and website-specific settings, but keep your global settings." ) ) { await clearStylesData(); } } catch (error) { console.error("Error setting repository URL:", error); showRepositoryUrlStatus(`Error saving URL: ${error.message}`, "error"); } } async function resetRepositoryUrl() { try { repositoryUrlInput.value = DEFAULT_REPOSITORY_URL; await browser.storage.local.set({ [REPOSITORY_URL_KEY]: DEFAULT_REPOSITORY_URL, }); showRepositoryUrlStatus("Repository URL reset to default", "success"); // Prompt to clear styles data if ( confirm( "Would you like to clear existing styles data to avoid conflicts?\n\nThis will clear saved styles and website-specific settings, but keep your global settings." ) ) { await clearStylesData(); } } catch (error) { console.error("Error resetting repository URL:", error); showRepositoryUrlStatus(`Error resetting URL: ${error.message}`, "error"); } } async function clearStylesData() { try { // Get all storage data to filter what to keep and what to remove const allData = await browser.storage.local.get(null); // Create a new object with just the data we want to keep const dataToKeep = {}; // Keep global settings if (allData[BROWSER_STORAGE_KEY]) { dataToKeep[BROWSER_STORAGE_KEY] = allData[BROWSER_STORAGE_KEY]; } // Keep repository URL if (allData[REPOSITORY_URL_KEY]) { dataToKeep[REPOSITORY_URL_KEY] = allData[REPOSITORY_URL_KEY]; } // Clear all storage first await browser.storage.local.clear(); // Then restore the data we want to keep await browser.storage.local.set(dataToKeep); // Refresh the data display loadAllData(); showRepositoryUrlStatus("Styles data cleared successfully", "success"); } catch (error) { console.error("Error clearing styles data:", error); showRepositoryUrlStatus(`Error clearing data: ${error.message}`, "error"); } } function showRepositoryUrlStatus(message, type) { repositoryUrlStatus.textContent = message; repositoryUrlStatus.className = `repository-url-status status-${type}`; // Clear the message after 5 seconds setTimeout(() => { repositoryUrlStatus.textContent = ""; repositoryUrlStatus.className = "repository-url-status"; }, 5000); } 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 saveTransparencySettings(isDisabled) { try { const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); const settings = data[BROWSER_STORAGE_KEY] || {}; // Update the disableTransparency setting settings.disableTransparency = isDisabled; await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); // No notification - just save the setting silently } catch (error) { console.error("Error saving transparency settings:", error); } } // New functions to save hover and footer settings async function saveHoverSettings(isDisabled) { try { const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); const settings = data[BROWSER_STORAGE_KEY] || {}; // Update the disableHover setting settings.disableHover = isDisabled; await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); // No notification - just save the setting silently } catch (error) { console.error("Error saving hover settings:", error); } } async function saveFooterSettings(isDisabled) { try { const data = await browser.storage.local.get(BROWSER_STORAGE_KEY); const settings = data[BROWSER_STORAGE_KEY] || {}; // Update the disableFooter setting settings.disableFooter = isDisabled; await browser.storage.local.set({ [BROWSER_STORAGE_KEY]: settings }); // No notification - just save the setting silently } catch (error) { console.error("Error saving footer settings:", error); } } // Export settings functionality async function exportSettings() { try { // Retrieve all storage data to find site-specific settings const allData = await browser.storage.local.get(null); // Extract only the settings we want to backup const settingsToBackup = { [BROWSER_STORAGE_KEY]: allData[BROWSER_STORAGE_KEY] || {}, [SKIP_FORCE_THEMING_KEY]: allData[SKIP_FORCE_THEMING_KEY] || [], [SKIP_THEMING_KEY]: allData[SKIP_THEMING_KEY] || [], [REPOSITORY_URL_KEY]: allData[REPOSITORY_URL_KEY] || DEFAULT_REPOSITORY_URL, }; // Also extract site-specific settings (keys that start with BROWSER_STORAGE_KEY.) const siteSpecificSettings = {}; for (const [key, value] of Object.entries(allData)) { if (key.startsWith(BROWSER_STORAGE_KEY + ".")) { siteSpecificSettings[key] = value; } } // Add export timestamp and version const manifest = browser.runtime.getManifest(); const exportData = { exportDate: new Date().toISOString(), addonVersion: manifest.version, settings: settingsToBackup, siteSettings: siteSpecificSettings, }; // Convert to JSON const jsonData = JSON.stringify(exportData, null, 2); // Create a blob and download link const blob = new Blob([jsonData], { type: "application/json" }); const url = URL.createObjectURL(blob); // Create a temporary anchor and trigger download const a = document.createElement("a"); a.href = url; a.download = `zen-internet-settings-${ new Date().toISOString().split("T")[0] }.json`; document.body.appendChild(a); a.click(); // Cleanup setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 0); // Show success message showImportStatus("Settings exported successfully!", "success"); } catch (error) { console.error("Error exporting settings:", error); showImportStatus(`Export failed: ${error.message}`, "error"); } } // Import settings functionality async function importSettings(event) { try { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = async (e) => { try { const importData = JSON.parse(e.target.result); // Validate the imported data structure if ( !importData.settings || !importData.settings[BROWSER_STORAGE_KEY] ) { throw new Error("Invalid settings file format"); } // Confirm the import if ( confirm( `Are you sure you want to import settings from ${importData.exportDate}? This will overwrite your current settings.` ) ) { // First store the global settings, lists, and repository URL const importOperations = { [BROWSER_STORAGE_KEY]: importData.settings[BROWSER_STORAGE_KEY], [SKIP_FORCE_THEMING_KEY]: importData.settings[SKIP_FORCE_THEMING_KEY] || [], [SKIP_THEMING_KEY]: importData.settings[SKIP_THEMING_KEY] || [], [REPOSITORY_URL_KEY]: importData.settings[REPOSITORY_URL_KEY] || DEFAULT_REPOSITORY_URL, }; // Then add any site-specific settings if they exist if (importData.siteSettings) { for (const [key, value] of Object.entries( importData.siteSettings )) { importOperations[key] = value; } } // Apply all settings at once await browser.storage.local.set(importOperations); showImportStatus( "Settings imported successfully! Reloading...", "success" ); // Reload the page after a short delay setTimeout(() => { window.location.reload(); }, 1500); } else { // User cancelled importFileInput.value = ""; showImportStatus("Import cancelled", "error"); } } catch (parseError) { console.error("Error parsing import file:", parseError); showImportStatus(`Import failed: ${parseError.message}`, "error"); } }; reader.readAsText(file); } catch (error) { console.error("Error handling import:", error); showImportStatus(`Import failed: ${error.message}`, "error"); } } // Helper function to show import status messages function showImportStatus(message, type) { importStatusElement.textContent = message; importStatusElement.className = `import-status status-${type}`; // Clear the message after 5 seconds setTimeout(() => { importStatusElement.textContent = ""; importStatusElement.className = "import-status"; }, 5000); } 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); // Set the toggle states disableTransparencyToggle.checked = globalSettings.disableTransparency || false; // Set new toggle states disableHoverToggle.checked = globalSettings.disableHover || false; disableFooterToggle.checked = globalSettings.disableFooter || false; // Display skip/enable lists for both forced and non-forced websites const skipForceList = data[SKIP_FORCE_THEMING_KEY] || []; const skipThemingList = data[SKIP_THEMING_KEY] || []; displayCombinedSkipLists( skipForceList, skipThemingList, globalSettings.whitelistMode, globalSettings.whitelistStyleMode ); // 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 = `