Add persistent per-screen brightness, standby and clock settings

This commit is contained in:
Max Gramser
2026-09-12 13:31:18 +02:00
parent 747ec4cceb
commit 917b3d6d09
18 changed files with 634 additions and 240 deletions
+97
View File
@@ -65,6 +65,99 @@ function select(id) {
renderScreens();
renderTiles();
renderResults();
renderSettings();
}
const settingDefinitions = [
["standby_enabled", "Automatisch standby", "check", true],
["standby_seconds", "Standby na", "minutes", 600, 1, 1440],
["brightness", "Helderheid normaal", "range", 100, 5, 100],
["standby_brightness", "Helderheid in standby", "range", 20, 0, 100],
["night_enabled", "Nachtstand gebruiken", "check", true],
["night_brightness", "Helderheid in nachtstand", "range", 10, 0, 100],
["night_start", "Nachtstand vanaf", "time", 1320],
["night_end", "Nachtstand tot", "time", 420],
["show_clock", "Klok tonen", "check", true],
["clock_24h", "24-uursklok (uit = 12 uur)", "check", true],
["home_on_standby", "Na standby terug naar pagina 1", "check", false],
];
function renderSettings() {
const values = {
...Object.fromEntries(
settingDefinitions.map(([key, , , value]) => [key, value]),
),
...layout.settings,
};
const container = $("#settings-fields");
container.replaceChildren();
for (const [key, title, kind, , min, max] of settingDefinitions) {
const label = node(
"label",
undefined,
`setting ${kind === "check" ? "setting-check" : ""}`,
);
const caption = node("span", title),
input = node("input"),
output = node("output");
input.id = `setting-${key}`;
input.type =
kind === "check" ? "checkbox" : kind === "minutes" ? "number" : kind;
input.setAttribute("aria-label", title);
input.required = kind === "minutes" || kind === "time";
if (kind === "check") input.checked = values[key];
else if (kind === "time")
input.value = `${String(Math.floor(values[key] / 60)).padStart(2, "0")}:${String(values[key] % 60).padStart(2, "0")}`;
else {
input.min = min;
input.max = max;
input.step = 1;
input.value = kind === "minutes" ? values[key] / 60 : values[key];
}
const updateOutput = () =>
(output.textContent =
kind === "range"
? `${input.value}%`
: kind === "minutes"
? "minuten"
: "");
updateOutput();
input.oninput = () => {
if (!input.checkValidity() || input.value === "") return;
let value = kind === "check" ? input.checked : Number(input.value);
if (kind === "time") {
const [h, m] = input.value.split(":").map(Number);
value = h * 60 + m;
}
if (kind === "minutes") value *= 60;
layout.settings = { ...values, ...layout.settings, [key]: value };
// A lower normal brightness also lowers any higher standby levels.
if (key === "brightness")
for (const dim of ["standby_brightness", "night_brightness"]) {
layout.settings[dim] = Math.min(layout.settings[dim], value);
const other = $(`#setting-${dim}`);
other.value = layout.settings[dim];
other.parentElement.querySelector("output").textContent =
`${other.value}%`;
}
updateOutput();
markDirty();
};
label.append(caption, input, output);
container.append(label);
}
renderSettingsSupport();
}
function renderSettingsSupport() {
const version =
inventory.screens.find((s) => s.id === selected)?.firmware || "";
const parts = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/.exec(version);
const supported =
parts &&
(Number(parts[1]) > 0 ||
Number(parts[2]) > 1 ||
(Number(parts[2]) === 1 && Number(parts[3]) >= 2));
$("#settings-support").textContent = supported
? "Opslaan stuurt je instellingen direct naar dit scherm. Ze blijven ook na een herstart bewaard."
: "Eenmalig firmware 0.1.2 of nieuwer installeren via ESPHome. Je kunt de instellingen alvast bewaren; oudere firmware gebruikt ze nog niet.";
}
function renderScreens() {
$("#screens").replaceChildren();
@@ -220,6 +313,7 @@ async function refresh() {
: "Verbinding met Home Assistant herstellen…";
$("#connection").classList.toggle("online", inventory.connected);
renderScreens();
if (selected) renderSettingsSupport();
if (!selected && inventory.screens.length) select(inventory.screens[0].id);
} catch {
$("#connection").textContent =
@@ -228,6 +322,9 @@ async function refresh() {
}
$("#save").onclick = async () => {
if (busy) return;
for (const input of document.querySelectorAll("#settings-fields input")) {
if (!input.reportValidity()) return;
}
busy = true;
$("#save").disabled = true;
try {
+13
View File
@@ -86,6 +86,19 @@
<div id="results" aria-live="polite"></div>
</div>
</div>
<details class="screen-settings" open>
<summary>
Scherminstellingen
<span class="hint">Helderheid, rustmomenten en weergave</span>
</summary>
<p class="hint" id="settings-support"></p>
<div class="settings-grid" id="settings-fields"></div>
<p class="hint">
Nachturen gelden voor de helderheid tijdens standby. De eerste
aanraking maakt het scherm wakker; de volgende bedient je huis.
Gelijke begin- en eindtijd schakelen het nachtvenster uit.
</p>
</details>
<footer class="savebar">
<div>
<strong id="dirty">Alles opgeslagen</strong
+53
View File
@@ -563,3 +563,56 @@ textarea {
margin-left: 0;
}
}
.screen-settings {
margin: 28px 0 20px;
border-top: 1px solid var(--line);
padding-top: 20px;
}
.screen-settings summary {
cursor: pointer;
font-size: 18px;
font-weight: 700;
}
.settings-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px 28px;
margin: 20px 0;
}
.setting {
padding: 14px;
border: 1px solid var(--line);
border-radius: 12px;
}
.setting output {
display: block;
color: var(--muted);
font-size: 13px;
}
.setting input[type="range"] {
padding: 0;
accent-color: var(--accent);
min-height: 32px;
}
.setting-check {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.setting-check input {
width: 22px;
height: 22px;
flex-shrink: 0;
margin: 0;
accent-color: var(--accent);
}
.setting-check output {
display: none;
}
@media (max-width: 640px) {
.settings-grid {
grid-template-columns: 1fr;
}
}