From adf86104de89b0d710fbf64ff317ef455ab98df7 Mon Sep 17 00:00:00 2001 From: mdtaufiquekhan Date: Tue, 20 May 2025 02:44:24 +0530 Subject: [PATCH] Add import/export feature for extension profiles --- README.md | 4 ++ TODO.md | 6 ++- js/importExport.js | 89 +++++++++++++++++++++++++++++++++++++++++ profiles.html | 12 ++++++ styles/importExport.css | 7 ++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 js/importExport.js create mode 100644 styles/importExport.css diff --git a/README.md b/README.md index 193e1f8..8908a7a 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ Follow us in Twitter: [@ExtensityChrome](https://twitter.com/ExtensityChrome) ### What's new: +v1.15.0 (May 2025) +- **New Feature**: Import/Export extension profiles as `.json` files. +- Allows users to back up and restore profile settings. + v1.14.0 (Sep 2024) - **New Feature**: Dark Mode (based on system settings) - Migrated from CSSO to SASS diff --git a/TODO.md b/TODO.md index c18fa3f..34c101d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,8 @@ ## Extensity TO-DOs -- Allow import and export of profiles configuration - Dark mode +- [ ] Implement automatic sync with Chrome profile + - Keep manual import/export functionality for advanced users or backups + - Enable seamless syncing of profiles using `chrome.storage.sync` + - Profiles should automatically back up and restore across devices + - Add toggle option in settings to enable/disable auto-sync \ No newline at end of file diff --git a/js/importExport.js b/js/importExport.js new file mode 100644 index 0000000..a102d6f --- /dev/null +++ b/js/importExport.js @@ -0,0 +1,89 @@ +// Wait for the DOM to fully load before attaching event listeners +document.addEventListener('DOMContentLoaded', () => { + + // 🔹 EXPORT PROFILES FROM chrome.storage.sync + const exportBtn = document.getElementById('exportSettings'); + if (exportBtn) { + exportBtn.addEventListener('click', () => { + + // Fetch 'profiles' from Chrome's sync storage + chrome.storage.sync.get(['profiles'], (data) => { + + // If no profiles exist, alert the user and exit + if (!data.profiles || Object.keys(data.profiles).length === 0) { + alert('!No profiles found to export.'); + return; + } + + // Convert profiles data to a JSON blob + const blob = new Blob( + [JSON.stringify(data.profiles, null, 2)], + { type: 'application/json' } + ); + + // Create a temporary download link for the JSON file + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + const dateStr = new Date().toISOString().split('T')[0]; + a.href = url; + a.download = `extensity-profiles-${dateStr}.json`; // Dynamic filename + a.click(); // Trigger the download + URL.revokeObjectURL(url); // Clean up the URL + }); + }); + } + + // 🔹 TRIGGER IMPORT FILE SELECTOR + const importBtn = document.getElementById('importSettings'); + if (importBtn) { + importBtn.addEventListener('click', () => { + // Simulate a click on the hidden file input + document.getElementById('importFile').click(); + }); + } + + // 🔹 HANDLE FILE INPUT CHANGE (IMPORT PROFILES) + const importFileInput = document.getElementById('importFile'); + if (importFileInput) { + importFileInput.addEventListener('change', (event) => { + const file = event.target.files[0]; + if (!file) return; // Exit if no file is selected + + const reader = new FileReader(); + + // When file is successfully read + reader.onload = function (e) { + try { + const importedProfiles = JSON.parse(e.target.result); + + // Validate the imported data + if (!importedProfiles || typeof importedProfiles !== 'object') { + alert('! Invalid or corrupt file.'); + return; + } + + // Save imported profiles into Chrome's sync storage + chrome.storage.sync.set({ profiles: importedProfiles }, () => { + + // Show a success message in the UI, if available + const msg = document.getElementById('save-result'); + if (msg) { + msg.classList.remove('hidden'); + msg.textContent = '| Profiles imported!'; + setTimeout(() => msg.classList.add('hidden'), 3000); + } else { + alert(':) Profiles imported! Please reload Extensity.'); + } + }); + + } catch (err) { + // Handle JSON parsing errors + alert('! Failed to parse JSON file.'); + } + }; + + // Start reading the file as text + reader.readAsText(file); + }); + } +}); diff --git a/profiles.html b/profiles.html index fa7e31c..da6dac1 100644 --- a/profiles.html +++ b/profiles.html @@ -3,6 +3,9 @@ Extensity Profiles + + + @@ -10,6 +13,8 @@ + +