feat(ui): add clear device presets action

Made-with: Cursor
This commit is contained in:
2026-04-21 00:44:38 +12:00
parent f6f299c3e5
commit 60485bc06a
3 changed files with 59 additions and 14 deletions

View File

@@ -214,6 +214,7 @@ document.addEventListener('DOMContentLoaded', () => {
const presetsCloseButton = document.getElementById('presets-close-btn');
const presetsList = document.getElementById('presets-list');
const presetsAddButton = document.getElementById('preset-add-btn');
const presetClearDeviceButton = document.getElementById('preset-clear-device-btn');
const presetEditorModal = document.getElementById('preset-editor-modal');
const presetEditorCloseButton = document.getElementById('preset-editor-close-btn');
const presetNameInput = document.getElementById('preset-name-input');
@@ -283,7 +284,8 @@ document.addEventListener('DOMContentLoaded', () => {
if (!input) {
return 0;
}
return parseInt(input.value, 10) || 0;
const n = parseInt(String(input.value).trim(), 10);
return Number.isFinite(n) ? n : 0;
};
const renderPresetColors = (colors, paletteRefs) => {
@@ -564,14 +566,18 @@ document.addEventListener('DOMContentLoaded', () => {
const nKey = `n${i}`;
const inputEl = document.getElementById(`preset-${nKey}-input`);
if (inputEl) {
if (preset[nKey] !== undefined) {
inputEl.value = preset[nKey] || 0;
if (preset[nKey] !== undefined && preset[nKey] !== null) {
const raw = preset[nKey];
const n = typeof raw === 'number' ? raw : parseInt(String(raw), 10);
inputEl.value = String(Number.isFinite(n) ? n : 0);
} else {
const label = nToLabel[nKey];
if (label && preset[label] !== undefined) {
inputEl.value = preset[label] || 0;
if (label && preset[label] !== undefined && preset[label] !== null) {
const rawL = preset[label];
const nL = typeof rawL === 'number' ? rawL : parseInt(String(rawL), 10);
inputEl.value = String(Number.isFinite(nL) ? nL : 0);
} else {
inputEl.value = 0;
inputEl.value = '0';
}
}
}
@@ -811,6 +817,10 @@ document.addEventListener('DOMContentLoaded', () => {
});
}
const hasPatternMeta =
patternConfig && typeof patternConfig === 'object' && Object.keys(patternConfig).length > 0;
const hasAnyNLabel = visibleNKeys.size > 0;
for (let i = 1; i <= 8; i++) {
const nKey = `n${i}`;
const labelEl = document.getElementById(`preset-${nKey}-label`);
@@ -824,7 +834,9 @@ document.addEventListener('DOMContentLoaded', () => {
if (groupEl) {
groupEl.style.display = show ? '' : 'none';
}
if (inputEl && !show) {
// Only clear hidden n inputs when we know this pattern's metadata (avoids wiping n3..n4
// while definitions are still loading, or when twinkle exists only as a driver file).
if (inputEl && !show && (hasAnyNLabel || hasPatternMeta)) {
inputEl.value = '0';
}
}
@@ -969,6 +981,30 @@ document.addEventListener('DOMContentLoaded', () => {
openEditor();
});
}
if (presetClearDeviceButton) {
presetClearDeviceButton.addEventListener('click', async () => {
const section = document.querySelector('.presets-section[data-zone-id]');
const deviceNames = tabDeviceNamesFromSection(section);
if (!deviceNames.length) {
alert('No devices found in the current zone.');
return;
}
if (!window.confirm('Clear all presets on current zone devices?')) {
return;
}
try {
const targetMacs =
typeof window.tabsManager !== 'undefined' &&
typeof window.tabsManager.resolveTabDeviceMacs === 'function'
? await window.tabsManager.resolveTabDeviceMacs(deviceNames)
: [];
await postDriverSequence([{ v: '1', clear_presets: true, save: true }], targetMacs);
} catch (error) {
console.error('Clear device presets failed:', error);
alert('Failed to clear presets on devices.');
}
});
}
const showAddPresetToTabModal = async (optionalTabId) => {
let zoneId = optionalTabId;
@@ -1405,6 +1441,14 @@ document.addEventListener('DOMContentLoaded', () => {
clearForm();
});
const coercePresetInt = (v, def = 0) => {
if (typeof v === 'number' && Number.isFinite(v)) {
return v;
}
const t = parseInt(String(v), 10);
return Number.isFinite(t) ? t : def;
};
// Build driver messages for a single preset; deliver via /presets/push (ESP-NOW + TCP).
// Send order:
// 1) preset payload (optionally with save)
@@ -1429,12 +1473,12 @@ const sendPresetViaEspNow = async (presetId, preset, deviceNames, saveToDevice =
? preset.brightness
: (typeof preset.br === 'number' ? preset.br : 127),
auto: typeof preset.auto === 'boolean' ? preset.auto : true,
n1: typeof preset.n1 === 'number' ? preset.n1 : 0,
n2: typeof preset.n2 === 'number' ? preset.n2 : 0,
n3: typeof preset.n3 === 'number' ? preset.n3 : 0,
n4: typeof preset.n4 === 'number' ? preset.n4 : 0,
n5: typeof preset.n5 === 'number' ? preset.n5 : 0,
n6: typeof preset.n6 === 'number' ? preset.n6 : 0,
n1: coercePresetInt(preset.n1),
n2: coercePresetInt(preset.n2),
n3: coercePresetInt(preset.n3),
n4: coercePresetInt(preset.n4),
n5: coercePresetInt(preset.n5),
n6: coercePresetInt(preset.n6),
},
},
};