support export and import
This commit is contained in:
@@ -52,6 +52,13 @@
|
||||
<div id="presetList" class="mt-4 space-y-2 max-h-40 overflow-y-auto pr-1">
|
||||
<!-- Saved presets -->
|
||||
</div>
|
||||
|
||||
<!-- Import/Export Presets -->
|
||||
<div class="flex gap-2 pt-2 border-t border-gray-100">
|
||||
<button id="exportPresets" class="flex-1 bg-white text-gray-600 text-[10px] py-1 rounded border border-gray-300 hover:bg-gray-50 transition-colors font-medium">导出预设</button>
|
||||
<button id="importPresets" class="flex-1 bg-white text-gray-600 text-[10px] py-1 rounded border border-gray-300 hover:bg-gray-50 transition-colors font-medium">导入预设</button>
|
||||
<input type="file" id="importInput" class="hidden" accept=".json">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
58
sidepanel.js
58
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');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user