feat(zones): persist per-zone brightness and update submodules

Store zone brightness in model/data flow, apply it in the zones UI, and record updated led-driver, led-simulator, and led-tool submodule pointers.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-04 22:49:06 +12:00
parent 827eb97203
commit 7ccab6fbc4
10 changed files with 300 additions and 51 deletions

View File

@@ -17,24 +17,26 @@ function applyBrightnessSliders(val) {
if (menuSlider) menuSlider.value = String(v);
}
async function saveGlobalBrightnessToServer(val) {
async function saveZoneBrightnessToServer(zoneId, val) {
if (!zoneId) return;
try {
const res = await fetch("/settings/settings", {
const res = await fetch(`/zones/${zoneId}`, {
method: "PUT",
headers: { "Content-Type": "application/json", Accept: "application/json" },
credentials: "same-origin",
body: JSON.stringify({ global_brightness: val }),
body: JSON.stringify({ brightness: val }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
console.warn("global_brightness save failed:", err.error || res.status);
console.warn("zone brightness save failed:", err.error || res.status);
}
} catch (e) {
console.warn("global_brightness save failed:", e);
console.warn("zone brightness save failed:", e);
}
}
function sendZoneBrightness(value) {
function sendZoneBrightness(zoneId, value) {
if (!zoneId) return;
const val = Math.max(0, Math.min(255, parseInt(value, 10) || 0));
const headerSlider = document.getElementById('header-brightness-slider');
const menuSlider = document.getElementById('menu-brightness-slider');
@@ -50,7 +52,7 @@ function sendZoneBrightness(value) {
brightnessSendTimeout = setTimeout(() => {
(async () => {
try {
await saveGlobalBrightnessToServer(val);
await saveZoneBrightnessToServer(zoneId, val);
const section = document.querySelector('.presets-section[data-zone-id]');
const names = typeof window.parseTabDeviceNames === 'function'
? window.parseTabDeviceNames(section)
@@ -550,11 +552,16 @@ async function loadZoneContent(zoneId) {
`;
// Keep header and menu brightness controls in sync.
const brightnessSlider = document.getElementById('header-brightness-slider');
const menuBrightnessSlider = document.getElementById('menu-brightness-slider');
if (menuBrightnessSlider && brightnessSlider) {
menuBrightnessSlider.value = brightnessSlider.value;
}
const zoneBrightness =
typeof zone.brightness === 'number'
? zone.brightness
: parseInt(String(zone.brightness ?? ''), 10);
const normalizedBrightness = Number.isFinite(zoneBrightness)
? Math.max(0, Math.min(255, Math.round(zoneBrightness)))
: 255;
applyBrightnessSliders(normalizedBrightness);
// Apply this zone's saved brightness when switching zones.
sendZoneBrightness(zoneId, normalizedBrightness);
// Trigger presets loading if the function exists
if (typeof renderTabPresets === 'function') {
@@ -1025,38 +1032,17 @@ document.addEventListener('DOMContentLoaded', () => {
const menuBrightnessSlider = document.getElementById('menu-brightness-slider');
const headerBrightnessSlider = document.getElementById('header-brightness-slider');
(async () => {
let fromServer = null;
try {
const res = await fetch('/settings', {
headers: { Accept: 'application/json' },
credentials: 'same-origin',
});
if (res.ok) {
const data = await res.json();
const g = data.global_brightness;
if (typeof g === 'number' && g >= 0 && g <= 255) {
fromServer = Math.round(g);
} else if (g != null && g !== '') {
const n = parseInt(String(g), 10);
if (!Number.isNaN(n) && n >= 0 && n <= 255) {
fromServer = n;
}
}
}
} catch (_) {}
if (fromServer !== null) {
applyBrightnessSliders(fromServer);
}
if (menuBrightnessSlider) {
menuBrightnessSlider.addEventListener('input', (e) => {
sendZoneBrightness(e.target.value);
if (!currentZoneId) return;
sendZoneBrightness(currentZoneId, e.target.value);
});
}
if (headerBrightnessSlider) {
headerBrightnessSlider.addEventListener('input', (e) => {
sendZoneBrightness(e.target.value);
if (!currentZoneId) return;
sendZoneBrightness(currentZoneId, e.target.value);
});
sendZoneBrightness(headerBrightnessSlider.value);
}
})();