From 6f023006dc74c9f4852a7d02ebf31685d2cead56 Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Wed, 11 Mar 2026 14:11:37 -0400 Subject: [PATCH] support export and import --- sidepanel.html | 7 ++++++ sidepanel.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/sidepanel.html b/sidepanel.html index d6b7d99..211f6ed 100644 --- a/sidepanel.html +++ b/sidepanel.html @@ -52,6 +52,13 @@
+ + +
+ + + +
diff --git a/sidepanel.js b/sidepanel.js index e953507..b8ba5a7 100644 --- a/sidepanel.js +++ b/sidepanel.js @@ -16,6 +16,11 @@ const presetList = document.getElementById('presetList'); const presetSelect = document.getElementById('presetSelect'); const runPresetBtn = document.getElementById('runPreset'); +// Import/Export Elements +const exportBtn = document.getElementById('exportPresets'); +const importBtn = document.getElementById('importPresets'); +const importInput = document.getElementById('importInput'); + // Collapsible logic const toggleConfig = document.getElementById('toggleConfig'); const configContent = document.getElementById('configContent'); @@ -101,6 +106,58 @@ addPresetBtn.addEventListener('click', async () => { cancelEditBtn.addEventListener('click', stopEditing); +// Export/Import Logic +exportBtn.addEventListener('click', async () => { + const { userPresets = DEFAULT_PRESETS } = await chrome.storage.local.get('userPresets'); + const blob = new Blob([JSON.stringify(userPresets, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `hardware-presets-${new Date().toISOString().split('T')[0]}.json`; + a.click(); + URL.revokeObjectURL(url); +}); + +importBtn.addEventListener('click', () => importInput.click()); + +importInput.addEventListener('change', (e) => { + const file = e.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = async (event) => { + try { + const importedPresets = JSON.parse(event.target.result); + if (!Array.isArray(importedPresets)) throw new Error('无效的预设文件格式'); + + const { userPresets = DEFAULT_PRESETS } = await chrome.storage.local.get('userPresets'); + + const choice = confirm('导入成功!\n点击 [确定] 将导入的预设合并到当前列表。\n点击 [取消] 将替换整个预设列表。'); + + let finalPresets; + if (choice) { + // Merge: Append with new IDs to prevent conflicts + const newItems = importedPresets.map(p => ({ + ...p, + id: Date.now().toString() + Math.random().toString(36).substr(2, 5) + })); + finalPresets = [...userPresets, ...newItems]; + } else { + finalPresets = importedPresets; + } + + await chrome.storage.local.set({ userPresets: finalPresets }); + currentPresets = finalPresets; + renderPresets(currentPresets); + alert('预设导入完成!'); + } catch (err) { + alert('导入失败: ' + err.message); + } + importInput.value = ''; // Reset input + }; + reader.readAsText(file); +}); + function startEditing(preset) { editingPresetId = preset.id; newPresetName.value = preset.name; @@ -112,7 +169,6 @@ function startEditing(preset) { addPresetBtn.classList.replace('text-indigo-700', 'text-white'); cancelEditBtn.classList.remove('hidden'); - // Ensure config is expanded so user can see inputs configContent.classList.remove('hidden'); configChevron.classList.add('rotate-180'); }